catalog: decoder and shell: fix incorrect logic in find matching

The find matching was incorrectly performed starting from the parent directroy
and not as intended from the entries of the parent directory.

Further, the match pattern passed from the catalog shell contains the absolute
path of the search entry point as prefix, so find() must always start from the
archive root. This is because the match pattern has to be stored in the selected
list for a subsequent restore-selected command in the shell.
All matching paths are shown as absolute paths with all contents in the subdir,
equal to what would be restored by the given pattern.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner 2019-12-17 13:15:45 +01:00 committed by Dietmar Maurer
parent 8af272fd14
commit 38d9a69875
2 changed files with 26 additions and 31 deletions

View File

@ -546,44 +546,35 @@ impl <R: Read + Seek> CatalogReader<R> {
pattern: &[MatchPatternSlice], pattern: &[MatchPatternSlice],
callback: &Box<fn(&[DirEntry])>, callback: &Box<fn(&[DirEntry])>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let node = entry.last().unwrap(); let parent = entry.last().unwrap();
if !node.is_directory() { if !parent.is_directory() {
match MatchPatternSlice::match_filename_include(
&CString::new(node.name.clone())?,
false,
pattern,
)? {
(MatchType::Positive, _) => callback(&entry),
_ => {}
}
return Ok(()) return Ok(())
} }
match MatchPatternSlice::match_filename_include( for e in self.read_dir(parent)? {
&CString::new(node.name.clone())?, match MatchPatternSlice::match_filename_include(
node.is_directory(), &CString::new(e.name.clone())?,
pattern, e.is_directory(),
)? { pattern,
(MatchType::Positive, _) => { )? {
callback(&entry); (MatchType::Positive, _) => {
let pattern = MatchPattern::from_line(b"**/*").unwrap().unwrap(); entry.push(e);
let child_pattern = vec![pattern.as_slice()]; callback(&entry);
for e in self.read_dir(node)? { let pattern = MatchPattern::from_line(b"**/*").unwrap().unwrap();
let child_pattern = vec![pattern.as_slice()];
self.find(&mut entry, &child_pattern, callback)?;
entry.pop();
}
(MatchType::PartialPositive, child_pattern)
| (MatchType::PartialNegative, child_pattern) => {
entry.push(e); entry.push(e);
self.find(&mut entry, &child_pattern, callback)?; self.find(&mut entry, &child_pattern, callback)?;
entry.pop(); entry.pop();
} }
_ => {}
} }
(MatchType::PartialPositive, child_pattern)
| (MatchType::PartialNegative, child_pattern) => {
for e in self.read_dir(node)? {
entry.push(e);
self.find(&mut entry, &child_pattern, callback)?;
entry.pop();
}
}
_ => {}
} }
Ok(()) Ok(())
} }
} }

View File

@ -495,7 +495,7 @@ fn restore_command(target: String, pattern: Option<String>) -> Result<(), Error>
/// Find entries in the catalog matching the given match pattern. /// Find entries in the catalog matching the given match pattern.
fn find_command(path: String, pattern: String, select: Option<bool>) -> Result<(), Error> { fn find_command(path: String, pattern: String, select: Option<bool>) -> Result<(), Error> {
Context::with(|ctx| { Context::with(|ctx| {
let mut path = ctx.canonical_path(&path)?; let path = ctx.canonical_path(&path)?;
if !path.last().unwrap().is_directory() { if !path.last().unwrap().is_directory() {
bail!("path should be a directory, not a file!"); bail!("path should be a directory, not a file!");
} }
@ -517,8 +517,12 @@ fn find_command(path: String, pattern: String, select: Option<bool>) -> Result<(
.ok_or_else(|| format_err!("invalid match pattern"))?; .ok_or_else(|| format_err!("invalid match pattern"))?;
let slice = vec![pattern.as_slice()]; let slice = vec![pattern.as_slice()];
// The match pattern all contain the prefix of the entry path in order to
// store them if selected, so the entry point for find is always the root
// directory.
let mut dir_stack = ctx.root.clone();
ctx.catalog.find( ctx.catalog.find(
&mut path, &mut dir_stack,
&slice, &slice,
&Box::new(|path: &[DirEntry]| println!("{:?}", Context::generate_cstring(path).unwrap())) &Box::new(|path: &[DirEntry]| println!("{:?}", Context::generate_cstring(path).unwrap()))
)?; )?;