Two opt-in scan diagnostics for the DVD decrypted-image defect

dvd_placement_invariant_on_a_real_folder checks, per title set, the sum
ifo.rs relies on: file_start_lba(VTS_nn_0.IFO) + vtstt_vobs must land on
VTS_nn_1.VOB. It reports all 13 sets correct on a real DVD folder, which
is what excluded placement as the cause.

dump_titles_for_an_image prints every title a scan produces with the
numbers canonical_title_order sorts on. It is what showed the real shape:
the same disc scans to 38 titles as a CSS image and 10 once decrypted,
with identical capacity and a byte-complete image.

Both are #[ignore]d and read their target from the environment, so they
cost the gate nothing and are there for whoever picks the defect up.
This commit is contained in:
Matthew Jackson
2026-08-05 19:33:58 -07:00
parent 35c5eedc20
commit 1f70398774
2 changed files with 90 additions and 83 deletions
+90
View File
@@ -734,3 +734,93 @@ fn write_and_mount_externally() {
"the OS mounted the image but read back different bytes"
);
}
/// Diagnostic (opt-in): verify the DVD placement invariant for every title set
/// in a REAL folder. `ifo.rs` derives a title's extents as
/// `file_start_lba(VTS_nn_0.IFO) + vtstt_vobs`, so that sum must land exactly on
/// `VTS_nn_1.VOB` or the mux reads the wrong sectors for that title.
///
/// Run with: `FMKV_DVD_FOLDER=/path/to/tree cargo test --lib
/// dvd_placement_invariant_on_a_real_folder -- --ignored --nocapture`
#[test]
#[ignore = "diagnostic: needs FMKV_DVD_FOLDER pointing at a real VIDEO_TS tree"]
fn dvd_placement_invariant_on_a_real_folder() {
let Ok(dir) = std::env::var("FMKV_DVD_FOLDER") else {
return;
};
let mut img = DirImage::open(std::path::Path::new(&dir)).expect("open");
let fs = udf::read_filesystem(&mut img).expect("udf");
let mut bad = 0;
for n in 1..=25u32 {
let ifo = format!("/VIDEO_TS/VTS_{n:02}_0.IFO");
let vob = format!("/VIDEO_TS/VTS_{n:02}_1.VOB");
let (Ok(ifo_lba), Ok(vob_lba)) = (
fs.file_start_lba(&mut img, &ifo),
fs.file_start_lba(&mut img, &vob),
) else {
continue;
};
let head = fs
.read_file_prefix(&mut img, &ifo, 0xC8)
.unwrap_or_default();
if head.len() < 0xC8 {
println!("VTS {n:02}: IFO shorter than 0xC8");
continue;
}
let vtstt = u32::from_be_bytes([head[0xC4], head[0xC5], head[0xC6], head[0xC7]]);
let want = ifo_lba + vtstt;
if want != vob_lba {
bad += 1;
}
println!(
"VTS {n:02}: ifo={ifo_lba} vtstt={vtstt} want={want} vob={vob_lba} {}",
if want == vob_lba { "ok" } else { "MISMATCH" }
);
}
println!("{bad} title set(s) misplaced");
assert_eq!(
bad, 0,
"the placement invariant must hold for every title set"
);
}
/// Diagnostic (opt-in): dump every title an image scan produces, with the
/// numbers `canonical_title_order` actually sorts on.
///
/// Run: `FMKV_IMAGE=/path/to.iso cargo test --lib dump_titles_for_an_image
/// -- --ignored --nocapture`
#[test]
#[ignore = "diagnostic: needs FMKV_IMAGE"]
fn dump_titles_for_an_image() {
let Ok(path) = std::env::var("FMKV_IMAGE") else {
return;
};
let (disc, _r) = crate::session::scan_iso(
std::path::Path::new(&path),
crate::disc::ScanOptions::default(),
)
.expect("scan");
println!(
"capacity_bytes={} format={:?} css_error={:?} titles={}",
disc.capacity_bytes,
disc.format,
disc.css.as_ref().map(|c| format!("{:?}", c.crack_span)),
disc.titles.len()
);
for (i, t) in disc.titles.iter().enumerate() {
println!(
" [{i}] playlist={:<16} dur={:>8.2}s size={:>12} extents={} streams={}",
t.playlist,
t.duration_secs,
t.size_bytes,
t.extents.len(),
t.streams.len()
);
for e in t.extents.iter().take(3) {
println!(
" extent lba={} sectors={}",
e.start_lba, e.sector_count
);
}
}
}