Each source implements next_key (a cursor over its candidates) instead of returning them all at once. The keydb hands its per-disc candidates out UK-first (UK > VK > MK > DK) so a stale/wrong VUK never pre-empts a good UK in the same entry; online and mapfile are one-shot. MultiSource composes sources in the caller's chosen order and resolve_and_apply drives the next_key -> decrypt_with loop, stopping at the first key that decrypts. read_sample_units moves here so the CLI and autorip share one content sampler.
47 lines
1.5 KiB
Rust
47 lines
1.5 KiB
Rust
//! Mapfile cache source (source #3).
|
|
//!
|
|
//! A rip's ddrescue-style mapfile persists the resolved unit keys in its
|
|
//! `# freemkv-uk:` header (written at sweep time when the disc was keyed). On
|
|
//! resume / deferred mux, that mapfile is the fastest source — the keys are
|
|
//! already resolved, no keydb parse and no network round-trip. This source
|
|
//! reads them back as a terminal [`Key::Unit`] candidate.
|
|
//!
|
|
//! It is keyed by the mapfile path (the disc identity is implicit in which
|
|
//! mapfile belongs to which rip), so it ignores [`DiscInputs`].
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use libfreemkv::disc::mapfile::Mapfile;
|
|
use libfreemkv::{DiscInputs, Key, KeySource};
|
|
|
|
/// A [`KeySource`] backed by a rip mapfile's persisted unit keys.
|
|
pub struct MapfileSource {
|
|
path: PathBuf,
|
|
/// The mapfile holds exactly one (terminal) UK set, so it is read once —
|
|
/// this flips true after the first `next_key`.
|
|
asked: bool,
|
|
}
|
|
|
|
impl MapfileSource {
|
|
/// A mapfile source reading the given `*.mapfile` path.
|
|
pub fn new(path: impl Into<PathBuf>) -> Self {
|
|
Self {
|
|
path: path.into(),
|
|
asked: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl KeySource for MapfileSource {
|
|
fn next_key(&mut self, _inputs: &DiscInputs) -> Option<Key> {
|
|
if self.asked {
|
|
return None;
|
|
}
|
|
self.asked = true;
|
|
// A missing/unreadable/keyless mapfile simply offers nothing.
|
|
let map = Mapfile::load(&self.path).ok()?;
|
|
let uks = map.unit_keys();
|
|
(!uks.is_empty()).then(|| Key::Unit(uks.to_vec()))
|
|
}
|
|
}
|