disc: Disc::unlocker_matrix() — registry-driven unlocker report
Returns each registered unlocker's name + whether it applies to this drive+disc (via the unlock bridge over all_unlockers()). Disc crypto kind derived in the library so the CLI and autorip render an identical, always- current report with no hardcoded names. Also adds a Drive::unlocker_name() runtime getter.
This commit is contained in:
@@ -2269,6 +2269,22 @@ impl Disc {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// The unlocker matrix for this scanned disc on `drive`: each REGISTERED
|
||||
/// unlocker's name + whether it applies to this drive + disc. Registry-driven
|
||||
/// (no hardcoded names) so the CLI and autorip render an identical, always-
|
||||
/// current report. The disc's crypto kind is derived here (in the library) so
|
||||
/// both apps agree.
|
||||
pub fn unlocker_matrix(&self, drive: &crate::Drive) -> Vec<(&'static str, bool)> {
|
||||
let kind = if self.aacs.is_some() || self.aacs_error.is_some() {
|
||||
freemkv_unlock::DiscKind::Aacs
|
||||
} else if self.css.is_some() || self.css_error.is_some() {
|
||||
freemkv_unlock::DiscKind::Css
|
||||
} else {
|
||||
freemkv_unlock::DiscKind::Unencrypted
|
||||
};
|
||||
crate::unlock_bridge::unlocker_matrix(&drive.drive_id, kind)
|
||||
}
|
||||
|
||||
/// The system-wide decrypt correctness gate.
|
||||
///
|
||||
/// Returns `Ok(())` when it is safe to proceed with a copy or mux, and a
|
||||
|
||||
@@ -226,6 +226,15 @@ impl Drive {
|
||||
crate::unlock_bridge::unlocker_name(&self.drive_id).is_some()
|
||||
}
|
||||
|
||||
/// The name of the drive unlocker that ACTUALLY unlocked this drive at
|
||||
/// `init()`, or `None` if none applied (unsupported drive, or the unlock
|
||||
/// failed). Distinct from [`has_profile`](Self::has_profile), which reports
|
||||
/// only an identity match: this is the runtime outcome. Apps render it in the
|
||||
/// user-facing unlocker report.
|
||||
pub fn unlocker_name(&self) -> Option<&str> {
|
||||
self.unlocker_name.as_deref()
|
||||
}
|
||||
|
||||
/// Access the SCSI transport for direct commands (used by CSS/AACS auth).
|
||||
pub fn scsi_mut(&mut self) -> &mut dyn ScsiTransport {
|
||||
self.scsi.as_mut()
|
||||
|
||||
@@ -124,6 +124,23 @@ pub(crate) fn run_unlockers(
|
||||
Err(fu::UnlockError::NotApplicable)
|
||||
}
|
||||
|
||||
/// Registry-driven unlocker matrix: each REGISTERED unlocker's name + whether it
|
||||
/// applies to this drive + disc, in dispatch order. Dynamic — sourced from
|
||||
/// `all_unlockers()`, so adding/removing an unlocker updates every report with no
|
||||
/// other change (no hardcoded names). Apps render the yes/no English from this
|
||||
/// typed list. Report-only: uses `applies_to`, not the phase-gated `matches`.
|
||||
pub(crate) fn unlocker_matrix(
|
||||
drive_id: &crate::identity::DriveId,
|
||||
kind: fu::DiscKind,
|
||||
) -> Vec<(&'static str, bool)> {
|
||||
let id = to_fu_drive_id(drive_id);
|
||||
let ctx = fu::UnlockCtx::new(&id, kind, &[]);
|
||||
fu::all_unlockers()
|
||||
.iter()
|
||||
.map(|u| (u.name(), u.applies_to(&ctx)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user