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:
parent
6fc053ed85
commit
90fc97af6a
|
@ -309,12 +309,12 @@ fn stat_command(path: String) -> Result<(), Error> {
|
||||||
// This is done by calling canonical_path(), which returns the full path
|
// This is done by calling canonical_path(), which returns the full path
|
||||||
// if it exists, error otherwise.
|
// if it exists, error otherwise.
|
||||||
let path = ctx.canonical_path(&path)?;
|
let path = ctx.canonical_path(&path)?;
|
||||||
let (item, _attr, size) = ctx.lookup(&path)?;
|
let item = ctx.lookup(&path)?;
|
||||||
let mut out = std::io::stdout();
|
let mut out = std::io::stdout();
|
||||||
out.write_all(b"File: ")?;
|
out.write_all(b"File: ")?;
|
||||||
out.write_all(item.filename.as_bytes())?;
|
out.write_all(item.filename.as_bytes())?;
|
||||||
out.write_all(&[b'\n'])?;
|
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: ")?;
|
out.write_all(b"Type: ")?;
|
||||||
match item.entry.mode as u32 & libc::S_IFMT {
|
match item.entry.mode as u32 & libc::S_IFMT {
|
||||||
libc::S_IFDIR => out.write_all(b"directory\n")?,
|
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
|
// Get the directory corresponding to the working directory from the
|
||||||
// archive.
|
// archive.
|
||||||
let cwd = ctx.current.clone();
|
let cwd = ctx.current.clone();
|
||||||
let (dir, _, _) = ctx.lookup(&cwd)?;
|
ctx.lookup(&cwd)?
|
||||||
dir
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.decoder
|
ctx.decoder
|
||||||
|
@ -681,27 +680,19 @@ impl Context {
|
||||||
///
|
///
|
||||||
/// This will actively navigate the archive by calling the corresponding
|
/// This will actively navigate the archive by calling the corresponding
|
||||||
/// decoder functionalities and is therefore very expensive.
|
/// decoder functionalities and is therefore very expensive.
|
||||||
fn lookup(
|
fn lookup(&mut self, absolute_path: &[DirEntry]) -> Result<DirectoryEntry, Error> {
|
||||||
&mut self,
|
|
||||||
absolute_path: &[DirEntry],
|
|
||||||
) -> Result<(DirectoryEntry, PxarAttributes, u64), Error> {
|
|
||||||
let mut current = self.decoder.root()?;
|
let mut current = self.decoder.root()?;
|
||||||
let (_, _, mut attr, mut size) = self.decoder.attributes(0)?;
|
|
||||||
// Ignore the archive root, don't need it.
|
// Ignore the archive root, don't need it.
|
||||||
for item in absolute_path.iter().skip(1) {
|
for item in absolute_path.iter().skip(1) {
|
||||||
match self
|
match self
|
||||||
.decoder
|
.decoder
|
||||||
.lookup(¤t, &OsStr::from_bytes(&item.name))?
|
.lookup(¤t, &OsStr::from_bytes(&item.name))?
|
||||||
{
|
{
|
||||||
Some((item, item_attr, item_size)) => {
|
Some(item) => current = item,
|
||||||
current = item;
|
|
||||||
attr = item_attr;
|
|
||||||
size = item_size;
|
|
||||||
}
|
|
||||||
// This should not happen if catalog an archive are consistent.
|
// This should not happen if catalog an archive are consistent.
|
||||||
None => bail!("no such file or directory in archive - inconsistent catalog"),
|
None => bail!("no such file or directory in archive - inconsistent catalog"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((current, attr, size))
|
Ok(current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,14 @@ pub struct DirectoryEntry {
|
||||||
start: u64,
|
start: u64,
|
||||||
/// Points past the goodbye table tail
|
/// Points past the goodbye table tail
|
||||||
end: u64,
|
end: u64,
|
||||||
|
/// Filename of entry
|
||||||
pub filename: OsString,
|
pub filename: OsString,
|
||||||
|
/// Entry (mode, permissions)
|
||||||
pub entry: PxarEntry,
|
pub entry: PxarEntry,
|
||||||
|
/// Extended attributes
|
||||||
|
pub xattr: PxarAttributes,
|
||||||
|
/// Payload size
|
||||||
|
pub size: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait to create ReadSeek Decoder trait objects.
|
/// Trait to create ReadSeek Decoder trait objects.
|
||||||
|
@ -59,11 +65,19 @@ impl Decoder {
|
||||||
let header: PxarHeader = self.inner.read_item()?;
|
let header: PxarHeader = self.inner.read_item()?;
|
||||||
check_ca_header::<PxarEntry>(&header, PXAR_ENTRY)?;
|
check_ca_header::<PxarEntry>(&header, PXAR_ENTRY)?;
|
||||||
let entry: PxarEntry = self.inner.read_item()?;
|
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 {
|
Ok(DirectoryEntry {
|
||||||
start: self.root_start,
|
start: self.root_start,
|
||||||
end: self.root_end,
|
end: self.root_end,
|
||||||
filename: OsString::new(), // Empty
|
filename: OsString::new(), // Empty
|
||||||
entry,
|
entry,
|
||||||
|
xattr,
|
||||||
|
size,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,12 +130,19 @@ impl Decoder {
|
||||||
}
|
}
|
||||||
check_ca_header::<PxarEntry>(&head, PXAR_ENTRY)?;
|
check_ca_header::<PxarEntry>(&head, PXAR_ENTRY)?;
|
||||||
let entry: PxarEntry = self.inner.read_item()?;
|
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 {
|
Ok(DirectoryEntry {
|
||||||
start: entry_start,
|
start: entry_start,
|
||||||
end,
|
end,
|
||||||
filename,
|
filename,
|
||||||
entry,
|
entry,
|
||||||
|
xattr,
|
||||||
|
size,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +294,7 @@ impl Decoder {
|
||||||
&mut self,
|
&mut self,
|
||||||
dir: &DirectoryEntry,
|
dir: &DirectoryEntry,
|
||||||
filename: &OsStr,
|
filename: &OsStr,
|
||||||
) -> Result<Option<(DirectoryEntry, PxarAttributes, u64)>, Error> {
|
) -> Result<Option<DirectoryEntry>, Error> {
|
||||||
let gbt = self.goodbye_table(Some(dir.start), dir.end)?;
|
let gbt = self.goodbye_table(Some(dir.start), dir.end)?;
|
||||||
let hash = compute_goodbye_hash(filename.as_bytes());
|
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
|
// 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
|
// case of directories, so the use of start offset is fine for both
|
||||||
// cases.
|
// 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
|
// Possible hash collision, need to check if the found entry is indeed
|
||||||
// the filename to lookup.
|
// the filename to lookup.
|
||||||
|
@ -308,8 +329,10 @@ impl Decoder {
|
||||||
end: *end,
|
end: *end,
|
||||||
filename: entry_name,
|
filename: entry_name,
|
||||||
entry,
|
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
|
// 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).
|
// from given index but skipping one more match (so hash at index itself).
|
||||||
|
|
Loading…
Reference in New Issue