Preserve I/O error from read_aacs_inputs ISO open

Disc::read_aacs_inputs opened the ISO via FileSectorSource::open and
mapped any failure to Error::AacsNoKeys (E7000), discarding the real
Error::IoError (E5000) and its OS errno. A missing or unreadable ISO
(ENOENT/EPERM) is an I/O fault, not a key-resolution failure; callers
that dispatch on the error code would wrongly tell the user to check
their keys when the ISO simply does not exist.

Propagate the open error unchanged and add a regression test asserting
a nonexistent ISO yields E_IO_ERROR, not E_AACS_NO_KEYS.
This commit is contained in:
Matthew Jackson
2026-06-23 03:59:55 -07:00
parent c9bf92cd6f
commit 662594ff40
+28 -2
View File
@@ -1508,8 +1508,12 @@ impl Disc {
/// out-of-band: obtain the key however you like, then apply it via
/// [`Disc::decrypt_with`]. libfreemkv never makes a network call.
pub fn read_aacs_inputs(iso_path: &std::path::Path) -> Result<(Vec<u8>, Vec<u8>)> {
let mut reader = crate::io::file_sector_source::FileSectorSource::open(iso_path)
.map_err(|_| Error::AacsNoKeys)?;
// Preserve the underlying open error (`Error::IoError`, E5000, carrying
// the OS errno) instead of collapsing ENOENT/EPERM/etc. into
// `Error::AacsNoKeys` (E7000). A missing or unreadable ISO is an I/O
// fault, not a key-resolution failure; callers that dispatch on
// `.code()` must be able to tell the two apart.
let mut reader = crate::io::file_sector_source::FileSectorSource::open(iso_path)?;
let udf_fs = udf::read_filesystem(&mut reader)?;
Self::read_aacs_inputs_from_reader(&mut reader, &udf_fs)
}
@@ -3394,6 +3398,28 @@ mod tests {
}
}
/// `read_aacs_inputs` on a missing/unreadable ISO must surface the real
/// I/O fault (`E_IO_ERROR`, 5000) carrying the OS errno — NOT `AacsNoKeys`
/// (7000). Collapsing ENOENT into a key error makes callers that dispatch
/// on `.code()` tell the user "no keys / check your KEYDB" when the actual
/// problem is that the ISO file does not exist.
#[test]
fn read_aacs_inputs_missing_iso_is_io_error_not_no_keys() {
let missing = std::path::Path::new("/nonexistent/freemkv/does-not-exist.iso");
let err = Disc::read_aacs_inputs(missing).expect_err("opening a nonexistent ISO must fail");
assert_eq!(
err.code(),
crate::error::E_IO_ERROR,
"missing ISO must map to E_IO_ERROR (5000), got {} ({err:?})",
err.code()
);
assert_ne!(
err.code(),
crate::error::E_AACS_NO_KEYS,
"missing ISO must not be reported as AacsNoKeys (7000)"
);
}
/// The sysfs probe only applies on Linux and only to `/`-delimited node
/// paths. A backslash-form path is never sysfs-probeable on any platform.
#[test]