From d7be81367997536dceb08a7be0014136a1f89df2 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Wed, 19 Apr 2023 20:08:47 +0200 Subject: libfstree: Make hard link resolution non-recursive Use the next_by_type pointer to create a list of all unresolved hard links and iterate over that list for link resolution. Signed-off-by: David Oberhollenzer --- include/fstree.h | 3 +++ lib/fstree/src/hardlink.c | 47 +++++++++++++++++++++-------------------------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/include/fstree.h b/include/fstree.h index 1d427a4..72cbc29 100644 --- a/include/fstree.h +++ b/include/fstree.h @@ -102,6 +102,9 @@ struct fstree_t { /* linear linked list of all regular files */ tree_node_t *files; + + /* linear linked list of all unresolved hard links */ + tree_node_t *links_unresolved; }; /* diff --git a/lib/fstree/src/hardlink.c b/lib/fstree/src/hardlink.c index 6973b4c..81636c7 100644 --- a/lib/fstree/src/hardlink.c +++ b/lib/fstree/src/hardlink.c @@ -53,31 +53,6 @@ static int resolve_link(fstree_t *fs, tree_node_t *node) return 0; } -static int resolve_hard_links_dfs(fstree_t *fs, tree_node_t *n) -{ - tree_node_t *it; - - if (n->mode == FSTREE_MODE_HARD_LINK) { - if (resolve_link(fs, n)) - goto fail_link; - } else if (S_ISDIR(n->mode)) { - for (it = n->data.children; it != NULL; it = it->next) { - if (resolve_hard_links_dfs(fs, it)) - return -1; - } - } - - return 0; -fail_link: { - char *path = fstree_get_path(n); - fprintf(stderr, "Resolving hard link '%s' -> '%s': %s\n", - path == NULL ? n->name : path, n->data.target, - strerror(errno)); - free(path); -} - return -1; -} - tree_node_t *fstree_add_hard_link(fstree_t *fs, const char *path, const char *target) { @@ -98,10 +73,30 @@ tree_node_t *fstree_add_hard_link(fstree_t *fs, const char *path, n->mode = FSTREE_MODE_HARD_LINK; } + n->next_by_type = fs->links_unresolved; + fs->links_unresolved = n; + return n; } int fstree_resolve_hard_links(fstree_t *fs) { - return resolve_hard_links_dfs(fs, fs->root); + while (fs->links_unresolved != NULL) { + tree_node_t *n = fs->links_unresolved; + + if (resolve_link(fs, n)) { + char *path = fstree_get_path(n); + fprintf(stderr, + "Resolving hard link '%s' -> '%s': %s\n", + path == NULL ? n->name : path, n->data.target, + strerror(errno)); + free(path); + return -1; + } + + fs->links_unresolved = n->next_by_type; + n->next_by_type = NULL; + } + + return 0; } -- cgit v1.2.3