pxar::decoder::Decoder: include xattrs and payload size in DirectoryEntry.

By reading and including xattrs and payload size in struct `DirectoryEntry`,
the tuple of return types is avoided and the code is simpler.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner 2020-01-09 16:26:33 +01:00 committed by Dietmar Maurer
parent 6fc053ed85
commit 90fc97af6a
2 changed files with 32 additions and 18 deletions

View File

@ -309,12 +309,12 @@ fn stat_command(path: String) -> Result<(), Error> {
// This is done by calling canonical_path(), which returns the full path
// if it exists, error otherwise.
let path = ctx.canonical_path(&path)?;
let (item, _attr, size) = ctx.lookup(&path)?;
let item = ctx.lookup(&path)?;
let mut out = std::io::stdout();
out.write_all(b"File: ")?;
out.write_all(item.filename.as_bytes())?;
out.write_all(&[b'\n'])?;
out.write_all(format!("Size: {}\n", size).as_bytes())?;
out.write_all(format!("Size: {}\n", item.size).as_bytes())?;
out.write_all(b"Type: ")?;
match item.entry.mode as u32 & libc::S_IFMT {
libc::S_IFDIR => out.write_all(b"directory\n")?,
@ -463,8 +463,7 @@ fn restore_command(target: String, pattern: Option<String>) -> Result<(), Error>
// Get the directory corresponding to the working directory from the
// archive.
let cwd = ctx.current.clone();
let (dir, _, _) = ctx.lookup(&cwd)?;
dir
ctx.lookup(&cwd)?
};
ctx.decoder
@ -681,27 +680,19 @@ impl Context {
///
/// This will actively navigate the archive by calling the corresponding
/// decoder functionalities and is therefore very expensive.
fn lookup(
&mut self,
absolute_path: &[DirEntry],
) -> Result<(DirectoryEntry, PxarAttributes, u64), Error> {
fn lookup(&mut self, absolute_path: &[DirEntry]) -> Result<DirectoryEntry, Error> {
let mut current = self.decoder.root()?;
let (_, _, mut attr, mut size) = self.decoder.attributes(0)?;
// Ignore the archive root, don't need it.
for item in absolute_path.iter().skip(1) {
match self
.decoder
.lookup(&current, &OsStr::from_bytes(&item.name))?
{
Some((item, item_attr, item_size)) => {
current = item;
attr = item_attr;
size = item_size;
}
Some(item) => current = item,
// This should not happen if catalog an archive are consistent.
None => bail!("no such file or directory in archive - inconsistent catalog"),
}
}
Ok((current, attr, size))
Ok(current)
}
}

View File

@ -23,8 +23,14 @@ pub struct DirectoryEntry {
start: u64,
/// Points past the goodbye table tail
end: u64,
/// Filename of entry
pub filename: OsString,
/// Entry (mode, permissions)
pub entry: PxarEntry,
/// Extended attributes
pub xattr: PxarAttributes,
/// Payload size
pub size: u64,
}
/// Trait to create ReadSeek Decoder trait objects.
@ -59,11 +65,19 @@ impl Decoder {
let header: PxarHeader = self.inner.read_item()?;
check_ca_header::<PxarEntry>(&header, PXAR_ENTRY)?;
let entry: PxarEntry = self.inner.read_item()?;
let (header, xattr) = self.inner.read_attributes()?;
let size = match header.htype {
PXAR_PAYLOAD => header.size - HEADER_SIZE,
_ => 0,
};
Ok(DirectoryEntry {
start: self.root_start,
end: self.root_end,
filename: OsString::new(), // Empty
entry,
xattr,
size,
})
}
@ -116,12 +130,19 @@ impl Decoder {
}
check_ca_header::<PxarEntry>(&head, PXAR_ENTRY)?;
let entry: PxarEntry = self.inner.read_item()?;
let (header, xattr) = self.inner.read_attributes()?;
let size = match header.htype {
PXAR_PAYLOAD => header.size - HEADER_SIZE,
_ => 0,
};
Ok(DirectoryEntry {
start: entry_start,
end,
filename,
entry,
xattr,
size,
})
}
@ -273,7 +294,7 @@ impl Decoder {
&mut self,
dir: &DirectoryEntry,
filename: &OsStr,
) -> Result<Option<(DirectoryEntry, PxarAttributes, u64)>, Error> {
) -> Result<Option<DirectoryEntry>, Error> {
let gbt = self.goodbye_table(Some(dir.start), dir.end)?;
let hash = compute_goodbye_hash(filename.as_bytes());
@ -298,7 +319,7 @@ impl Decoder {
// the start of an item (PXAR_FILENAME) or the GOODBYE_TAIL_MARKER in
// case of directories, so the use of start offset is fine for both
// cases.
let (entry_name, entry, attr, payload_size) = self.attributes(*start)?;
let (entry_name, entry, xattr, size) = self.attributes(*start)?;
// Possible hash collision, need to check if the found entry is indeed
// the filename to lookup.
@ -308,8 +329,10 @@ impl Decoder {
end: *end,
filename: entry_name,
entry,
xattr,
size,
};
return Ok(Some((dir_entry, attr, payload_size)));
return Ok(Some(dir_entry));
}
// Hash collision, check the next entry in the goodbye table by starting
// from given index but skipping one more match (so hash at index itself).