0.18 round 2 (decrypt dedup): adopt DecryptingSectorSource at the two
existing call sites — sweep producer and DiscStream demux Round 1 shipped the DecryptingSectorSource decorator (libfreemkv/src/sector/decrypting.rs) but the existing decrypt sites kept calling crate::decrypt::decrypt_sectors inline. This commit migrates both: - Disc::sweep (disc/mod.rs): producer wraps the input reader in DecryptingSectorSource::new(reader, keys) before the read loop. The inline decrypt_sectors call goes away — read_sectors yields plaintext directly. - DiscStream (mux/disc.rs): constructor wraps the underlying Box<dyn SectorReader> in DecryptingSectorSource so the internal fill_extents / read path sees plaintext bytes. The DecryptKeys field stays on DiscStream for metadata-side use; it just no longer drives decryption. Disc::patch carried the same inline decrypt step at three call sites (main read, backtrack read, non-NOT_READY retry read). All three migrated onto the same wrapping for a single audit surface. Two small support changes carry the migration without touching the round-1 decorator shape: - sector/mod.rs gains specific SectorSource impls for &mut dyn SectorReader and Box<dyn SectorReader>, mirroring std's Read forwarding pattern. Generic blankets would conflict with the existing SectorReader → SectorSource blanket under the orphan rule (downstream could impl SectorReader for &mut U), so the impls are scoped to the dyn-trait shape we actually consume. - sector/decrypting.rs gains DecryptingSectorSource::set_keys so DiscStream::set_raw() can flip the wrapped reader to a DecryptKeys::None pass-through without rebuilding the decorator (which would require moving the inner Box out from behind &mut self). After this commit, grep `decrypt_sectors` in src/ shows the function definition, its single use inside DecryptingSectorSource, plus comments only. One audit surface for AACS / CSS / passthrough correctness. Behaviour-preserving: same plaintext bytes flow through; the only difference is which type owns the decrypt step. See freemkv-private/memory/0_18_redesign.md. Single contributor: MattJackson.
This commit is contained in:
+35
-35
@@ -1372,6 +1372,7 @@ impl Disc {
|
||||
opts: &SweepOptions,
|
||||
) -> Result<CopyResult> {
|
||||
use crate::io::{DEFAULT_PIPELINE_DEPTH, Pipeline};
|
||||
use crate::sector::{DecryptingSectorSource, SectorSource};
|
||||
use sweep::{ProgressSnapshot, SweepSink, WorkItem, try_recv_progress};
|
||||
|
||||
let total_bytes = self.capacity_sectors as u64 * 2048;
|
||||
@@ -1381,6 +1382,15 @@ impl Disc {
|
||||
crate::decrypt::DecryptKeys::None
|
||||
};
|
||||
|
||||
// Wrap the producer-side reader once so every read_sectors call
|
||||
// yields plaintext. `DecryptKeys::None` makes the decorator a
|
||||
// pass-through, so the wrapping is cheap when --raw / unencrypted
|
||||
// discs are being swept and we keep the pipeline shape uniform.
|
||||
// Replaces the inline `decrypt::decrypt_sectors` calls that used
|
||||
// to live in this loop and in the bisect inner loop below.
|
||||
let mut reader = DecryptingSectorSource::new(reader, keys);
|
||||
let reader = &mut reader;
|
||||
|
||||
// Mapfile: load if resuming, else wipe + recreate.
|
||||
let mapfile_path = self.mapfile_for(path);
|
||||
if !opts.resume {
|
||||
@@ -1528,14 +1538,10 @@ impl Disc {
|
||||
}
|
||||
read_ctx.bridge_degradation_count = 0;
|
||||
|
||||
// Decrypt on producer; consumer expects plaintext.
|
||||
if opts.decrypt {
|
||||
crate::decrypt::decrypt_sectors(
|
||||
&mut buf[..block_bytes as usize],
|
||||
&keys,
|
||||
0,
|
||||
)?;
|
||||
}
|
||||
// Plaintext: the wrapped reader (DecryptingSectorSource)
|
||||
// applied AACS / CSS in-place during read_sectors above.
|
||||
// The consumer thread sees decrypted bytes; the
|
||||
// pre-0.18 inline decrypt_sectors call lived here.
|
||||
|
||||
// Move the batch into the channel via fresh
|
||||
// owned Vec. The producer's `buf` is reused
|
||||
@@ -1591,16 +1597,9 @@ impl Disc {
|
||||
) {
|
||||
Ok(_) => {
|
||||
read_ctx.on_success();
|
||||
// Decrypt single sector before send. Pre-split
|
||||
// bisect path silently skipped this — encrypted
|
||||
// bytes were written for bisect-recovered sectors.
|
||||
if opts.decrypt {
|
||||
crate::decrypt::decrypt_sectors(
|
||||
&mut sector_buf,
|
||||
&keys,
|
||||
0,
|
||||
)?;
|
||||
}
|
||||
// Plaintext via the wrapping
|
||||
// DecryptingSectorSource — same
|
||||
// decrypt path the batch read takes.
|
||||
if pipe
|
||||
.send(WorkItem::BisectGood {
|
||||
pos: write_pos,
|
||||
@@ -1959,6 +1958,7 @@ impl Disc {
|
||||
opts: &PatchOpts,
|
||||
) -> Result<PatchOutcome> {
|
||||
use crate::io::pipeline::{Pipeline, WRITE_THROUGH_DEPTH};
|
||||
use crate::sector::{DecryptingSectorSource, SectorSource};
|
||||
use patch::{PatchItem, PatchSink};
|
||||
|
||||
const BRIDGE_DEGRADATION_PAUSE_SECS: u64 = 10;
|
||||
@@ -1987,6 +1987,15 @@ impl Disc {
|
||||
crate::decrypt::DecryptKeys::None
|
||||
};
|
||||
|
||||
// Wrap the producer-side reader once so every read_sectors
|
||||
// call (the main recovery read, the backtrack read, and the
|
||||
// non-NOT_READY retry read) yields plaintext. Replaces three
|
||||
// inline decrypt_sectors call sites that all keyed off the
|
||||
// same `keys`. `DecryptKeys::None` keeps the unencrypted /
|
||||
// --raw path a pass-through.
|
||||
let mut reader = DecryptingSectorSource::new(reader, keys);
|
||||
let reader = &mut reader;
|
||||
|
||||
let is_regular = std::fs::metadata(path)
|
||||
.map(|m| m.file_type().is_file())
|
||||
.unwrap_or(false);
|
||||
@@ -2412,9 +2421,9 @@ impl Disc {
|
||||
"Read succeeded"
|
||||
);
|
||||
}
|
||||
if opts.decrypt {
|
||||
crate::decrypt::decrypt_sectors(&mut buf[..bytes], &keys, 0)?;
|
||||
}
|
||||
// Plaintext: DecryptingSectorSource applied AACS / CSS
|
||||
// in-place during the read_sectors call above. The
|
||||
// pre-0.18 inline decrypt_sectors call lived here.
|
||||
let write_start = std::time::Instant::now();
|
||||
tracing::debug!(
|
||||
target: "freemkv::disc",
|
||||
@@ -2503,13 +2512,9 @@ impl Disc {
|
||||
) {
|
||||
Ok(_) => {
|
||||
blocks_read_ok += 1;
|
||||
if opts.decrypt {
|
||||
crate::decrypt::decrypt_sectors(
|
||||
&mut buf[..bt_bytes],
|
||||
&keys,
|
||||
0,
|
||||
)?;
|
||||
}
|
||||
// Plaintext via DecryptingSectorSource
|
||||
// wrapping; same path the main read
|
||||
// takes above.
|
||||
send_or_abort(
|
||||
&pipe,
|
||||
PatchItem::Recovered {
|
||||
@@ -2652,13 +2657,8 @@ impl Disc {
|
||||
"Retry succeeded after non-NOT_READY error"
|
||||
);
|
||||
|
||||
if opts.decrypt {
|
||||
crate::decrypt::decrypt_sectors(
|
||||
&mut buf[..bytes],
|
||||
&keys,
|
||||
0,
|
||||
)?;
|
||||
}
|
||||
// Plaintext via DecryptingSectorSource;
|
||||
// same path the original read takes.
|
||||
let write_start = std::time::Instant::now();
|
||||
tracing::debug!(
|
||||
target: "freemkv::disc",
|
||||
|
||||
Reference in New Issue
Block a user