Name update
This commit is contained in:
@@ -31,7 +31,9 @@ pub fn lookup(iso_path: &Path, in_iso_path: &str) -> Option<FileLocation> {
|
||||
.split('/')
|
||||
.filter(|c| !c.is_empty())
|
||||
.collect();
|
||||
if components.is_empty() { return None; }
|
||||
if components.is_empty() {
|
||||
return None;
|
||||
}
|
||||
walk(&mut f, root.offset, root.length, &components)
|
||||
}
|
||||
|
||||
@@ -40,11 +42,16 @@ fn read_root_directory(f: &mut std::fs::File) -> Option<FileLocation> {
|
||||
let mut pvd = [0u8; 2048];
|
||||
f.seek(SeekFrom::Start(16 * SECTOR)).ok()?;
|
||||
f.read_exact(&mut pvd).ok()?;
|
||||
if pvd[0] != 0x01 || &pvd[1..6] != b"CD001" { return None; }
|
||||
if pvd[0] != 0x01 || &pvd[1..6] != b"CD001" {
|
||||
return None;
|
||||
}
|
||||
// Root directory record is at offset 156, length 34.
|
||||
let rec = &pvd[156..156 + 34];
|
||||
let (offset, length) = parse_dir_record_ext(rec)?;
|
||||
Some(FileLocation { offset: offset * SECTOR, length })
|
||||
Some(FileLocation {
|
||||
offset: offset * SECTOR,
|
||||
length,
|
||||
})
|
||||
}
|
||||
|
||||
/// Walk components down the directory tree starting at `dir_offset`.
|
||||
@@ -66,21 +73,29 @@ fn walk(
|
||||
if len == 0 {
|
||||
// Padding to sector boundary.
|
||||
let next = (i / SECTOR as usize + 1) * SECTOR as usize;
|
||||
if next <= i { break; }
|
||||
if next <= i {
|
||||
break;
|
||||
}
|
||||
i = next;
|
||||
continue;
|
||||
}
|
||||
if i + len > dir.len() { break; }
|
||||
if i + len > dir.len() {
|
||||
break;
|
||||
}
|
||||
let rec = &dir[i..i + len];
|
||||
let name = dir_record_name(rec);
|
||||
let is_dir = (rec.get(25).copied().unwrap_or(0) & 0x02) != 0;
|
||||
// Skip "." (0x00) and ".." (0x01) pseudo-entries.
|
||||
let is_pseudo = matches!(rec.get(32).copied(), Some(1)) && rec.get(33).copied() == Some(0x00)
|
||||
let is_pseudo = matches!(rec.get(32).copied(), Some(1))
|
||||
&& rec.get(33).copied() == Some(0x00)
|
||||
|| matches!(rec.get(32).copied(), Some(1)) && rec.get(33).copied() == Some(0x01);
|
||||
if !is_pseudo && name.eq_ignore_ascii_case(target) {
|
||||
let (child_off, child_len) = parse_dir_record_ext(rec)?;
|
||||
if rest.is_empty() && !is_dir {
|
||||
return Some(FileLocation { offset: child_off * SECTOR, length: child_len });
|
||||
return Some(FileLocation {
|
||||
offset: child_off * SECTOR,
|
||||
length: child_len,
|
||||
});
|
||||
} else if !rest.is_empty() && is_dir {
|
||||
return walk(f, child_off * SECTOR, child_len, rest);
|
||||
}
|
||||
@@ -94,7 +109,9 @@ fn walk(
|
||||
/// Layout per ISO9660: bytes 2..10 extent LBA (LE+BE duplicate), 10..18
|
||||
/// data length (LE+BE duplicate). We trust the little-endian copy.
|
||||
fn parse_dir_record_ext(rec: &[u8]) -> Option<(u64, u64)> {
|
||||
if rec.len() < 34 { return None; }
|
||||
if rec.len() < 34 {
|
||||
return None;
|
||||
}
|
||||
let lba = u32::from_le_bytes(rec[2..6].try_into().ok()?) as u64;
|
||||
let len = u32::from_le_bytes(rec[10..14].try_into().ok()?) as u64;
|
||||
Some((lba, len))
|
||||
@@ -104,9 +121,15 @@ fn parse_dir_record_ext(rec: &[u8]) -> Option<(u64, u64)> {
|
||||
/// `;1` version suffix.
|
||||
fn dir_record_name(rec: &[u8]) -> String {
|
||||
let name_len = *rec.get(32).unwrap_or(&0) as usize;
|
||||
if name_len == 0 || rec.len() < 33 + name_len { return String::new(); }
|
||||
if name_len == 0 || rec.len() < 33 + name_len {
|
||||
return String::new();
|
||||
}
|
||||
let raw = &rec[33..33 + name_len];
|
||||
let s = String::from_utf8_lossy(raw).to_string();
|
||||
// Strip `;N` version suffix.
|
||||
if let Some(i) = s.rfind(';') { s[..i].to_string() } else { s }
|
||||
if let Some(i) = s.rfind(';') {
|
||||
s[..i].to_string()
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user