From: Alain Spineux Date: Fri, 3 Jun 2022 09:51:51 +0000 (+0200) Subject: Fix #9209 lsmark don't walk through unselected directory X-Git-Tag: Beta-15.0.0~533 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3cae5f12b09701592aae2b60b03280feb64c367;p=thirdparty%2Fbacula.git Fix #9209 lsmark don't walk through unselected directory - 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 --- diff --git a/bacula/src/dird/ua_tree.c b/bacula/src/dird/ua_tree.c index 55712413b..d30631796 100644 --- a/bacula/src/dird/ua_tree.c +++ b/bacula/src/dird/ua_tree.c @@ -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; } diff --git a/bacula/src/lib/tree.h b/bacula/src/lib/tree.h index e7aff21e2..0cb85d47e 100644 --- a/bacula/src/lib/tree.h +++ b/bacula/src/lib/tree.h @@ -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 */