aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-04-19 20:08:47 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-04-19 20:08:47 +0200
commitd7be81367997536dceb08a7be0014136a1f89df2 (patch)
treeebbe773721b8e055b7d67a4b4c5246685c90e2e6
parenta872319cab2f56f207c39d6fd436741e661b809a (diff)
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 <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/fstree.h3
-rw-r--r--lib/fstree/src/hardlink.c47
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;
}