Stop the HD-DVD VTI read and the extract progress channel from hiding loss

Two audit fixes plus two consistency cleanups, all in the changed 1.6.5 surface:

- hddvd: the VTI clip-order read used `.ok()`, flattening an unreadable
  authored order (a scratched sector under the .vti — the name came from the
  directory, so it is never "absent") into "no order" with no diagnostic. The
  sibling clip-extent arms log every read failure with its code; this one now
  does too, then falls back to the per-clip heuristic exactly as an unauthored
  disc would. Behaviour is otherwise unchanged; the loud line is the point.

- extract: the progress sink hardcoded bytes_unreadable_total: 0 and counted
  every zero-filled hole as good, so a progress-only consumer saw a holed
  extraction climb to a clean 100%. Thread the running unreadable total through
  and report the real good/unreadable split. The authoritative ExtractResult was
  already truthful; only the live channel lied.

- labels: correct a stale comment that described testlog's old lock-based
  capture; it now installs one global subscriber and routes to a thread-local
  sink.

- ps: import SYSTEM_HEADER from consts instead of re-declaring 0xBB, matching
  its sibling stream-id constants and the file's single-source rule.
This commit is contained in:
Matthew Jackson
2026-08-19 09:10:26 -07:00
parent 341e079e1e
commit 7abcfaab72
4 changed files with 61 additions and 21 deletions
+26 -4
View File
@@ -907,10 +907,32 @@ impl Disc {
}
// Authored clip order from the VTI clip table (empty if no VTI).
let order: Vec<String> = vti_name
.and_then(|n| udf_fs.read_file(reader, &format!("/HVDVD_TS/{n}")).ok())
.map(|b| parse_vti_clip_order(&b))
.unwrap_or_default();
//
// The VTI name came from `ts_dir.entries`, so a failed read here is a
// real I/O error (a scratched sector under the `.vti`), never an absent
// file. `.ok()` used to flatten the two — dropping the authored order
// with no diagnostic, so a split feature then composed from the per-clip
// heuristic and the operator was never told the authored order existed
// but could not be read. The clip-extent arms below log every read
// failure with its own code; this one now does too. The fallback itself
// is unchanged (no order => per-clip, exactly as an unauthored disc),
// because there is nothing to compose from without the table. Logging is
// exempt from the no-English rule (errors stay numeric).
let order: Vec<String> = match vti_name {
None => Vec::new(),
Some(n) => match udf_fs.read_file(reader, &format!("/HVDVD_TS/{n}")) {
Ok(bytes) => parse_vti_clip_order(&bytes),
Err(e) => {
tracing::warn!(
target: "freemkv::disc",
vti = ?n,
code = e.code(),
"authored clip order unreadable; falling back to the per-clip heuristic"
);
Vec::new()
}
},
};
// Resolve each clip's physical extents once, keyed by lower-case name.
let mut clip_extents: BTreeMap<String, (String, u64, Vec<Extent>)> = BTreeMap::new();