Add scan_iso entry point for file-backed ISO scans
Introduce libfreemkv::scan_iso(path, opts) -> (Disc, Box<dyn SectorSource>), the file-backed counterpart to DiscSession::scan. It is the single place that opens a FileSectorSource, reads its capacity, and runs Disc::scan_image, returning the scanned Disc plus a reusable reader over the same image so consumers stop hand-rolling that triple. Add an integration test that materialises a minimal synthetic UDF image to a real file, asserts scan_iso matches the manual open+scan_image composition, and confirms the returned reader is still usable (capacity + sector read). Also covers open-failure and scan-failure error propagation.
This commit is contained in:
+1
-1
@@ -146,7 +146,7 @@ pub use drive::{Drive, DriveStatus, find_drive};
|
||||
// stop hand-rolling `open → wait_ready → init → probe_disc → identify → scan`.
|
||||
// Owns the `Drive` by value; forwards consumer-built key material into
|
||||
// `ScanOptions` (the library derives no certs — see `KeySpec`).
|
||||
pub use session::{DeviceTarget, DiscSession, KeySpec};
|
||||
pub use session::{DeviceTarget, DiscSession, KeySpec, scan_iso};
|
||||
|
||||
// ─── Errors ─────────────────────────────────────────────────────────────────
|
||||
//
|
||||
|
||||
+25
-2
@@ -17,8 +17,8 @@ use crate::disc::{Disc, DiscId, DriveCredentials, ScanOptions};
|
||||
use crate::drive::{Drive, find_drive};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::keysource::KeySource;
|
||||
use crate::sector::SectorSource;
|
||||
use std::path::PathBuf;
|
||||
use crate::sector::{FileSectorSource, SectorSource};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Which optical device a [`DiscSession`] should open.
|
||||
pub enum DeviceTarget {
|
||||
@@ -190,6 +190,29 @@ impl DiscSession {
|
||||
}
|
||||
}
|
||||
|
||||
/// Scan an ISO image's structure from a file path, returning the scanned
|
||||
/// [`Disc`] together with a reusable [`SectorSource`] over the same file.
|
||||
///
|
||||
/// This is the file-backed counterpart to [`DiscSession::scan`]: it is the one
|
||||
/// place that opens a [`FileSectorSource`], reads its capacity, and runs
|
||||
/// [`Disc::scan_image`], so consumers (CLI, autorip) stop hand-rolling that
|
||||
/// triple and stop constructing the low-level reader themselves. No SCSI, no
|
||||
/// handshake, no key resolution — AACS resolution during the scan uses only
|
||||
/// whatever `opts` already carries (mirroring how `Disc::scan_image` forwards
|
||||
/// `ScanOptions`).
|
||||
///
|
||||
/// The returned reader is a fresh handle positioned at the start of the image;
|
||||
/// callers that need to sample ciphertext (key resolution) or feed a mux can
|
||||
/// reuse it directly rather than re-opening the file. `Disc::scan_image` reads
|
||||
/// only through the same reader, and all reads are LBA-addressed, so the
|
||||
/// handle is fully reusable afterward.
|
||||
pub fn scan_iso(path: &Path, opts: ScanOptions) -> Result<(Disc, Box<dyn SectorSource>)> {
|
||||
let mut reader = FileSectorSource::open(path)?;
|
||||
let capacity = reader.capacity_sectors();
|
||||
let disc = Disc::scan_image(&mut reader, capacity, &opts)?;
|
||||
Ok((disc, Box::new(reader)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user