src/pxar/decoder.rs: split functionality of list_dir into list_dir and goodbye_table

In order to read the contents of the goodbye table while keeping the
functionality of list_dir in place as is.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner 2019-09-09 18:27:24 +02:00 committed by Dietmar Maurer
parent ac12570e99
commit d00097a0e6

View File

@ -112,32 +112,33 @@ impl<R: Read + Seek, F: Fn(&Path) -> Result<(), Error>> Decoder<R, F> {
}) })
} }
pub fn list_dir(&mut self, dir: &DirectoryEntry) -> Result<Vec<DirectoryEntry>, Error> { /// Return the goodbye table based on the provided end offset.
let start = dir.start; ///
let end = dir.end; /// Get the goodbye table entries and the start and end offsets of the
/// items they reference.
//println!("list_dir1: {} {}", start, end); /// If the start offset is provided, we use that to check the consistency of
/// the data, else the start offset calculated based on the goodbye tail is
if (end - start) < (HEADER_SIZE + GOODBYE_ITEM_SIZE) { /// used.
bail!("detected short object [{}..{}]", start, end); pub(crate) fn goodbye_table(
} &mut self,
start: Option<u64>,
end: u64,
) -> Result<Vec<(PxarGoodbyeItem, u64, u64)>, Error> {
self.seek(SeekFrom::Start(end - GOODBYE_ITEM_SIZE))?; self.seek(SeekFrom::Start(end - GOODBYE_ITEM_SIZE))?;
let item: PxarGoodbyeItem = self.inner.read_item()?; let tail: PxarGoodbyeItem = self.inner.read_item()?;
if tail.hash != PXAR_GOODBYE_TAIL_MARKER {
if item.hash != PXAR_GOODBYE_TAIL_MARKER { bail!("missing goodbye tail marker for object at offset {}", end);
bail!(
"missing goodbye tail marker for object [{}..{}]",
start,
end
);
} }
let goodbye_table_size = item.size; // If the start offset was provided, we use and check based on that.
// If not, we rely on the offset calculated from the goodbye table entry.
let start = start.unwrap_or(end - tail.offset - tail.size);
let goodbye_table_size = tail.size;
if goodbye_table_size < (HEADER_SIZE + GOODBYE_ITEM_SIZE) { if goodbye_table_size < (HEADER_SIZE + GOODBYE_ITEM_SIZE) {
bail!("short goodbye table size for object [{}..{}]", start, end); bail!("short goodbye table size for object [{}..{}]", start, end);
} }
let goodbye_inner_size = goodbye_table_size - HEADER_SIZE - GOODBYE_ITEM_SIZE; let goodbye_inner_size = goodbye_table_size - HEADER_SIZE - GOODBYE_ITEM_SIZE;
if (goodbye_inner_size % GOODBYE_ITEM_SIZE) != 0 { if (goodbye_inner_size % GOODBYE_ITEM_SIZE) != 0 {
bail!( bail!(
@ -148,13 +149,7 @@ impl<R: Read + Seek, F: Fn(&Path) -> Result<(), Error>> Decoder<R, F> {
} }
let goodbye_start = end - goodbye_table_size; let goodbye_start = end - goodbye_table_size;
if tail.offset != (goodbye_start - start) {
if item.offset != (goodbye_start - start) {
println!(
"DEBUG: {} {}",
u64::from_le(item.offset),
goodbye_start - start
);
bail!( bail!(
"wrong offset in goodbye tail marker for entry [{}..{}]", "wrong offset in goodbye tail marker for entry [{}..{}]",
start, start,
@ -164,7 +159,6 @@ impl<R: Read + Seek, F: Fn(&Path) -> Result<(), Error>> Decoder<R, F> {
self.seek(SeekFrom::Start(goodbye_start))?; self.seek(SeekFrom::Start(goodbye_start))?;
let head: PxarHeader = self.inner.read_item()?; let head: PxarHeader = self.inner.read_item()?;
if head.htype != PXAR_GOODBYE { if head.htype != PXAR_GOODBYE {
bail!( bail!(
"wrong goodbye table header type for entry [{}..{}]", "wrong goodbye table header type for entry [{}..{}]",
@ -177,11 +171,9 @@ impl<R: Read + Seek, F: Fn(&Path) -> Result<(), Error>> Decoder<R, F> {
bail!("wrong goodbye table size for entry [{}..{}]", start, end); bail!("wrong goodbye table size for entry [{}..{}]", start, end);
} }
let mut range_list = Vec::new(); let mut gb_entries = Vec::new();
for i in 0..goodbye_inner_size / GOODBYE_ITEM_SIZE { for i in 0..goodbye_inner_size / GOODBYE_ITEM_SIZE {
let item: PxarGoodbyeItem = self.inner.read_item()?; let item: PxarGoodbyeItem = self.inner.read_item()?;
if item.offset > (goodbye_start - start) { if item.offset > (goodbye_start - start) {
bail!( bail!(
"goodbye entry {} offset out of range [{}..{}] {} {} {}", "goodbye entry {} offset out of range [{}..{}] {} {} {}",
@ -198,13 +190,25 @@ impl<R: Read + Seek, F: Fn(&Path) -> Result<(), Error>> Decoder<R, F> {
if item_end > goodbye_start { if item_end > goodbye_start {
bail!("goodbye entry {} end out of range [{}..{}]", i, start, end); bail!("goodbye entry {} end out of range [{}..{}]", i, start, end);
} }
gb_entries.push((item, item_start, item_end));
}
range_list.push((item_start, item_end)); Ok(gb_entries)
}
pub fn list_dir(&mut self, dir: &DirectoryEntry) -> Result<Vec<DirectoryEntry>, Error> {
let start = dir.start;
let end = dir.end;
//println!("list_dir1: {} {}", start, end);
if (end - start) < (HEADER_SIZE + GOODBYE_ITEM_SIZE) {
bail!("detected short object [{}..{}]", start, end);
} }
let mut result = vec![]; let mut result = vec![];
let goodbye_table = self.goodbye_table(Some(start), end)?;
for (item_start, item_end) in range_list { for (_, item_start, item_end) in goodbye_table {
let entry = self.read_directory_entry(item_start, item_end)?; let entry = self.read_directory_entry(item_start, item_end)?;
//println!("ENTRY: {} {} {:?}", item_start, item_end, entry.filename); //println!("ENTRY: {} {} {:?}", item_start, item_end, entry.filename);
result.push(entry); result.push(entry);