Files
libfreemkv/docs/image-writer.md
T
Matthew Jackson 6e14fc0c0c libfreemkv: 1.7.0 groundwork — sector-recycle soundness + CI hardening
Security
- Remove the unsafe Vec::set_len over recycled sector buffers — UB reachable
  from safe code (GHSA-j8ww-f5fg-9pmh, low). Uses Vec::resize; pooling unchanged.

CI / tooling
- clippy on stable with the MSRV single-sourced from Cargo.toml; cargo-deny
  dependency-audit gate with first-party git sources allowed (#15); audience-based
  comment-guard (#17).

Docs
- README (keydb ownership, BD-J parser count), drive-access transport/reset
  notes, mux timeline module-doc links.
2026-09-02 12:40:55 -07:00

36 lines
1.7 KiB
Markdown

# `src/io/image_writer.rs`
## Why this is not `freemkv_engine::copy`
The engine's `copy` is the RECOVERY path — mapfile sidecar, `--multipass`
sweep/patch, damage-jump, ECC-aware batching, auto-resume. Every one of those
exists because an optical drive returns read errors on marginal media. A
file-backed or synthesized source has no marginal media: a read either
succeeds or the underlying file is broken, and retrying it is pointless.
Routing a non-drive source through the recovery path is not merely wasteful,
it is wrong. Its mapfile identity check compares AACS unit keys and the VID,
both of which are empty for an already-decrypted source, so identity passes
for ANY such source: a second run with a different input to the same output
path would resume over the previous image and produce wrong content at exit
zero. Keeping the two paths separate makes that unrepresentable.
So: drive sources get `freemkv_engine::copy`. Everything else gets this.
## `write_image` rationale
The output is a faithful image of whatever the source presents — decrypted
if the caller wrapped the source in a
[`DecryptingSectorSource`](../src/sector/decrypting.rs), ciphertext if it did
not. `write_image` performs no decryption itself and makes no decryption
decision; that belongs to the caller, which knows whether the run is
`--raw`.
On cancellation the partial file is left in place — the caller decides
whether a partial image is worth keeping, and deleting a multi-gigabyte file
the user may want to inspect is not this function's call to make.
A short read from the source is treated as an error rather than zero-filled:
silently padding a truncated source would produce an image that looks
complete and is not.