]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Fix #9209 lsmark don't walk through unselected directory
authorAlain Spineux <alain@baculasystems.com>
Fri, 3 Jun 2022 09:51:51 +0000 (11:51 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 14 Sep 2023 11:56:58 +0000 (13:56 +0200)
- this fix explore the tree once and mark all directory
  that old marked file (at any sub level)
- then the lsmark code can display the parent directory
  only if they have marked sub-children

bacula/src/dird/ua_tree.c
bacula/src/lib/tree.h

index 55712413bc648b171155e80c0f1028f6733330a6..d306317968c86896f61bab1fccc1018d4b82f922 100644 (file)
@@ -644,8 +644,28 @@ static int dot_lsmarkcmd(UAContext *ua, TREE_CTX *tree)
    return 1;
 }
 
+/* This function walk the tree and mark any parent directory that have children
+ * that have been marked by lsmark.
+ * Then the tree can be walked again by rlsmark() to display the files that
+ * are marked and the directory they are in
+ */
+static bool tree_node_init_extract_sub(TREE_NODE *tnode)
+{
+   TREE_NODE *node;
+   bool ret = false;
+   foreach_child(node, tnode) {
+      bool ret1 = tree_node_init_extract_sub(node);
+      if ( ret1 || node->extract || node->extract_dir) {
+         tnode->extract_sub = true;
+         ret = true;
+      }
+   }
+   return ret;
+}
+
 /*
  * This recursive ls command that lists only the marked files
+ * tree_node_init_extract_sub() must be called before
  */
 static void rlsmark(UAContext *ua, TREE_NODE *tnode, int level)
 {
@@ -664,26 +684,27 @@ static void rlsmark(UAContext *ua, TREE_NODE *tnode, int level)
    }
    indent[j] = 0;
    foreach_child(node, tnode) {
-      if ((ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) &&
-          (node->extract || node->extract_dir)) {
-         const char *tag;
-         if (node->extract) {
-            tag = "*";
-         } else if (node->extract_dir) {
-            tag = "+";
-         } else {
-            tag = "";
-         }
+      const char *tag;
+      if (node->extract) {
+         tag = "*";
+      } else if (node->extract_dir) {
+         tag = "+";
+      } else {
+         tag = "";
+      }
+      if (((ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) &&
+          (node->extract || node->extract_dir)) || node->extract_sub) {
          ua->send_msg("%s%s%s%s\n", indent, tag, node->fname, tree_node_has_child(node)?"/":"");
-         if (tree_node_has_child(node)) {
-            rlsmark(ua, node, level+1);
-         }
+      }
+      if (node->extract_sub) {
+         rlsmark(ua, node, level+1);
       }
    }
 }
 
 static int lsmarkcmd(UAContext *ua, TREE_CTX *tree)
 {
+   tree_node_init_extract_sub(tree->node); /* identify dir that have marked sub-child */
    rlsmark(ua, tree->node, 0);
    return 1;
 }
index e7aff21e23f0325345f72fb2b37fe9fa9dea9640..0cb85d47e5308b77b4019e158ec17e5f38f5e6ff 100644 (file)
@@ -72,6 +72,7 @@ struct s_tree_node {
    unsigned int inserted: 1;          /* set when node newly inserted */
    unsigned int loaded: 1;            /* set when the dir is in the tree */
    unsigned int can_access: 1;        /* Can access to this node */
+   unsigned int extract_sub: 1;       /* set when a sub child must be extracted, used in lsmark only */
    struct s_tree_node *parent;
    struct s_tree_node *next;          /* next hash of FileIndex */
    struct delta_list *delta_list;     /* delta parts for this node */