From 15089abba230e8dd357e5f1bf6c9a1274ee37e77 Mon Sep 17 00:00:00 2001 From: Janis Date: Tue, 11 Apr 2023 01:58:37 +0200 Subject: [PATCH] proper compression handling of ranges --- btrfs/src/v2/volume.rs | 54 ++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/btrfs/src/v2/volume.rs b/btrfs/src/v2/volume.rs index 68b0141..6196fc7 100644 --- a/btrfs/src/v2/volume.rs +++ b/btrfs/src/v2/volume.rs @@ -572,63 +572,55 @@ impl Fs { let extent_start = *offset; let extent_end = extent_start + extent.len(); + // length of the entire range to be read let range_len = end.map(|end| end - start); + // bounds and length of the intersection of the current extent and + // the entire range to be read let start2 = start.min(extent_start); - let end = end.map(|end| end.max(extent_end)); - let len = end.map(|end| (end - start2)); + let end = end.map(|end| end.max(extent_end)).unwrap_or(extent.len()); + let len = end - start2; - if let (Some(len), Some(range_len)) = (len, range_len) { + // check if current extent intersects the range we want to read + if let Some(range_len) = range_len { range_len + range_len < len } else { start2 < extent_end } }) { - // let start = start.saturating_sub(offset); - - let end = end.map(|end| end - offset); + let end = end.map(|end| end - offset).unwrap_or(extent.len()); + let len = end - start; log::info!("reading {}..{:?} from extent.", start, end); let data: alloc::borrow::Cow<[u8]> = match &extent { - ExtentData::Inline { data, .. } => { - // TODO: handle compression and encryption - let data = if let Some(end) = end { - &data[start as usize..end as usize] - } else { - &data[start as usize..] - }; - - data.into() - } + ExtentData::Inline { data, .. } => (&data[start as usize..end as usize]).into(), ExtentData::Other(extent) => { let address = extent.address() + extent.offset() + start; - log::info!( - "address: {} = {} + {} + {}", - address, - extent.address(), - extent.offset(), - start - ); let address = self .volume .inner .offset_from_logical(address) .ok_or(Error::BadLogicalAddress)?; - let data = self - .volume - .inner - .read_range(address..address + end.unwrap_or(extent.num_bytes())) - .expect("bytes"); + + let range = address + ..(address + + match extent.extent_data1().compression() { + crate::structs::CompressionType::Zlib + | crate::structs::CompressionType::Lzo + | crate::structs::CompressionType::ZStd => extent.size(), // compressed size + _ => len, + }); + + let data = self.volume.inner.read_range(range).expect("bytes"); data.into() } }; log::info!("reading {} bytes from file", data.len()); - log::info!("extent type: {:?}", extent.header().ty()); log::info!("compression: {:?}", extent.header().compression()); - log::info!("raw bytes: {:?}", data); + let data = match extent.header().compression() { crate::structs::CompressionType::None => data, crate::structs::CompressionType::Zlib => { @@ -683,7 +675,7 @@ impl Fs { } }; - contents.extend_from_slice(&data); + contents.extend_from_slice(&data[..len as usize]); } Ok(contents)