diff --git a/crates/dvdbnd/src/lib.rs b/crates/dvdbnd/src/lib.rs index 332fa1f..df5046d 100644 --- a/crates/dvdbnd/src/lib.rs +++ b/crates/dvdbnd/src/lib.rs @@ -154,7 +154,17 @@ impl DvdBnd { #[cfg(unix)] let _ = mmap.advise(memmap2::Advice::Sequential); - Ok(DvdBndEntryReader::new(mmap.make_read_only()?)) + // DCXes dont have an unpadded size set + let effective_file_size = if entry.file_size != 0 { + entry.file_size + } else { + entry.file_size_with_padding + } as usize; + + Ok(DvdBndEntryReader::new( + mmap.make_read_only()?, + effective_file_size, + )) } None => Err(DvdBndEntryError::NotFound), } diff --git a/crates/dvdbnd/src/reader.rs b/crates/dvdbnd/src/reader.rs index 922063d..79e24fe 100644 --- a/crates/dvdbnd/src/reader.rs +++ b/crates/dvdbnd/src/reader.rs @@ -5,18 +5,25 @@ use memmap2::Mmap; pub struct DvdBndEntryReader { mmap: Mmap, position: usize, + length: usize, } impl DvdBndEntryReader { - pub fn new(mmap: Mmap) -> Self { - Self { mmap, position: 0 } + pub fn new(mmap: Mmap, length: usize) -> Self { + Self { + mmap, + position: 0, + length, + } } pub fn data(&self) -> &[u8] { - &self.mmap[..] + &self.mmap[..self.length] } } +// Do we really need this? With the length being a thing now to deal with the +// padding on the output this conversion is no longer lossless. impl From for Mmap { fn from(value: DvdBndEntryReader) -> Self { value.mmap @@ -25,7 +32,7 @@ impl From for Mmap { impl Read for DvdBndEntryReader { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - let mut data = &self.mmap[self.position..]; + let mut data = &self.data()[self.position..]; let read = data.read(buf)?; self.position += read; @@ -38,12 +45,12 @@ impl Seek for DvdBndEntryReader { fn seek(&mut self, pos: SeekFrom) -> std::io::Result { let new_pos = match pos { SeekFrom::Start(start_offset) => Some(start_offset as usize), - SeekFrom::End(end_offset) => self.mmap.len().checked_add_signed(end_offset as isize), + SeekFrom::End(end_offset) => self.data().len().checked_add_signed(end_offset as isize), SeekFrom::Current(offset) => self.position.checked_add_signed(offset as isize), } .ok_or(Error::other("invalid seek offset"))?; - if new_pos < self.mmap.len() { + if new_pos < self.data().len() { self.position = new_pos; Ok(self.position as u64) } else {