From 38d9a698753abdda3d41972fe7406ed6bcf7ac3e Mon Sep 17 00:00:00 2001 From: Christian Ebner Date: Tue, 17 Dec 2019 13:15:45 +0100 Subject: [PATCH] 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 --- src/backup/catalog.rs | 49 +++++++++++++++---------------------- src/backup/catalog_shell.rs | 8 ++++-- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/backup/catalog.rs b/src/backup/catalog.rs index 06f344fc..d0c5b293 100644 --- a/src/backup/catalog.rs +++ b/src/backup/catalog.rs @@ -546,44 +546,35 @@ impl CatalogReader { pattern: &[MatchPatternSlice], callback: &Box, ) -> Result<(), Error> { - let node = entry.last().unwrap(); - if !node.is_directory() { - match MatchPatternSlice::match_filename_include( - &CString::new(node.name.clone())?, - false, - pattern, - )? { - (MatchType::Positive, _) => callback(&entry), - _ => {} - } + let parent = entry.last().unwrap(); + if !parent.is_directory() { return Ok(()) } - match MatchPatternSlice::match_filename_include( - &CString::new(node.name.clone())?, - node.is_directory(), - pattern, - )? { - (MatchType::Positive, _) => { - callback(&entry); - let pattern = MatchPattern::from_line(b"**/*").unwrap().unwrap(); - let child_pattern = vec![pattern.as_slice()]; - for e in self.read_dir(node)? { + for e in self.read_dir(parent)? { + match MatchPatternSlice::match_filename_include( + &CString::new(e.name.clone())?, + e.is_directory(), + pattern, + )? { + (MatchType::Positive, _) => { + entry.push(e); + callback(&entry); + 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); self.find(&mut entry, &child_pattern, callback)?; 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(()) } } diff --git a/src/backup/catalog_shell.rs b/src/backup/catalog_shell.rs index f9d29eb9..b79a3a7c 100644 --- a/src/backup/catalog_shell.rs +++ b/src/backup/catalog_shell.rs @@ -495,7 +495,7 @@ fn restore_command(target: String, pattern: Option) -> Result<(), Error> /// Find entries in the catalog matching the given match pattern. fn find_command(path: String, pattern: String, select: Option) -> Result<(), Error> { Context::with(|ctx| { - let mut path = ctx.canonical_path(&path)?; + let path = ctx.canonical_path(&path)?; if !path.last().unwrap().is_directory() { bail!("path should be a directory, not a file!"); } @@ -517,8 +517,12 @@ fn find_command(path: String, pattern: String, select: Option) -> Result<( .ok_or_else(|| format_err!("invalid match pattern"))?; 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( - &mut path, + &mut dir_stack, &slice, &Box::new(|path: &[DirEntry]| println!("{:?}", Context::generate_cstring(path).unwrap())) )?;