]> git.proxmox.com Git - proxmox-backup.git/commitdiff
catalog: decoder and shell: fix incorrect logic in find matching
authorChristian Ebner <c.ebner@proxmox.com>
Tue, 17 Dec 2019 12:15:45 +0000 (13:15 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Tue, 17 Dec 2019 13:57:34 +0000 (14:57 +0100)
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>
src/backup/catalog.rs
src/backup/catalog_shell.rs

index 06f344fc8edf45a6bddc92e6f8a91fcee41f4b49..d0c5b2931d2af6899fdb7ece22f2e33b93311d37 100644 (file)
@@ -546,44 +546,35 @@ impl <R: Read + Seek> CatalogReader<R> {
         pattern: &[MatchPatternSlice],
         callback: &Box<fn(&[DirEntry])>,
     ) -> 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) => {
-                for e in self.read_dir(node)?  {
+                (MatchType::PartialPositive, child_pattern)
+                | (MatchType::PartialNegative, child_pattern) => {
                     entry.push(e);
                     self.find(&mut entry, &child_pattern, callback)?;
                     entry.pop();
                 }
+                _ => {}
             }
-            _ => {}
         }
+
         Ok(())
     }
 }
index f9d29eb94ffdbe1854d3ffb259750e897e4ad5d3..b79a3a7ce859751aac734b042e872bdd1a076f09 100644 (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.
 fn find_command(path: String, pattern: String, select: Option<bool>) -> 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<bool>) -> 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()))
         )?;