aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-04-06 14:53:49 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-04-06 18:07:59 +0200
commitc42e4fbbc6b175f843c4d0eeaaa9ead2d0e746b6 (patch)
treeadf2e61d9acdf5e18321d6ba0277dd3428de8fe3
parent23fab1d2b8164a99c5536581bb80769a620c65c0 (diff)
Cleanup: libfstree: move all the hardlink related code to hardlink.c
For some reason, the recursive hardlink resolution ended up in post process, calling into the non recrusive one in hardlink.c that wasn't used elsewhere. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/fstree.h4
-rw-r--r--lib/fstree/src/hardlink.c99
-rw-r--r--lib/fstree/src/post_process.c47
3 files changed, 78 insertions, 72 deletions
diff --git a/include/fstree.h b/include/fstree.h
index 7abf6f5..430574d 100644
--- a/include/fstree.h
+++ b/include/fstree.h
@@ -208,11 +208,11 @@ tree_node_t *fstree_add_hard_link(fstree_t *fs, const char *path,
const char *target);
/*
- Resolve a hard link node and replace it with a direct pointer to the target.
+ Try to resolve all hard links in the tree.
Returns 0 on success. On failure, errno is set.
*/
-int fstree_resolve_hard_link(fstree_t *fs, tree_node_t *node);
+int fstree_resolve_hard_links(fstree_t *fs);
void fstree_insert_sorted(tree_node_t *root, tree_node_t *n);
diff --git a/lib/fstree/src/hardlink.c b/lib/fstree/src/hardlink.c
index 2165b5f..9686219 100644
--- a/lib/fstree/src/hardlink.c
+++ b/lib/fstree/src/hardlink.c
@@ -11,32 +11,10 @@
#include <string.h>
#include <stdlib.h>
+#include <assert.h>
#include <errno.h>
-tree_node_t *fstree_add_hard_link(fstree_t *fs, const char *path,
- const char *target)
-{
- struct stat sb;
- tree_node_t *n;
-
- memset(&sb, 0, sizeof(sb));
- sb.st_mode = S_IFLNK | 0777;
-
- n = fstree_add_generic(fs, path, &sb, target);
- if (n != NULL) {
- if (canonicalize_name(n->data.target)) {
- free(n);
- errno = EINVAL;
- return NULL;
- }
-
- n->mode = FSTREE_MODE_HARD_LINK;
- }
-
- return n;
-}
-
-int fstree_resolve_hard_link(fstree_t *fs, tree_node_t *node)
+static int resolve_link(fstree_t *fs, tree_node_t *node)
{
tree_node_t *start = node;
@@ -74,3 +52,76 @@ int fstree_resolve_hard_link(fstree_t *fs, tree_node_t *node)
node->link_count++;
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;
+
+ assert(n->mode == FSTREE_MODE_HARD_LINK_RESOLVED);
+ it = n->data.target_node;
+
+ if (S_ISDIR(it->mode) && it->data.dir.visited)
+ goto fail_link_loop;
+ } else if (S_ISDIR(n->mode)) {
+ n->data.dir.visited = true;
+
+ for (it = n->data.dir.children; it != NULL; it = it->next) {
+ if (resolve_hard_links_dfs(fs, it))
+ return -1;
+ }
+
+ n->data.dir.visited = false;
+ }
+
+ 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;
+fail_link_loop: {
+ char *npath = fstree_get_path(n);
+ char *tpath = fstree_get_path(it);
+ fprintf(stderr, "Hard link loop detected in '%s' -> '%s'\n",
+ npath == NULL ? n->name : npath,
+ tpath == NULL ? it->name : tpath);
+ free(npath);
+ free(tpath);
+}
+ return -1;
+}
+
+tree_node_t *fstree_add_hard_link(fstree_t *fs, const char *path,
+ const char *target)
+{
+ struct stat sb;
+ tree_node_t *n;
+
+ memset(&sb, 0, sizeof(sb));
+ sb.st_mode = S_IFLNK | 0777;
+
+ n = fstree_add_generic(fs, path, &sb, target);
+ if (n != NULL) {
+ if (canonicalize_name(n->data.target)) {
+ free(n);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ n->mode = FSTREE_MODE_HARD_LINK;
+ }
+
+ return n;
+}
+
+int fstree_resolve_hard_links(fstree_t *fs)
+{
+ return resolve_hard_links_dfs(fs, fs->root);
+}
diff --git a/lib/fstree/src/post_process.c b/lib/fstree/src/post_process.c
index 088916b..940f93d 100644
--- a/lib/fstree/src/post_process.c
+++ b/lib/fstree/src/post_process.c
@@ -56,51 +56,6 @@ fail_ov:
return -1;
}
-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 (fstree_resolve_hard_link(fs, n))
- goto fail_link;
-
- assert(n->mode == FSTREE_MODE_HARD_LINK_RESOLVED);
- it = n->data.target_node;
-
- if (S_ISDIR(it->mode) && it->data.dir.visited)
- goto fail_link_loop;
- } else if (S_ISDIR(n->mode)) {
- n->data.dir.visited = true;
-
- for (it = n->data.dir.children; it != NULL; it = it->next) {
- if (resolve_hard_links_dfs(fs, it))
- return -1;
- }
-
- n->data.dir.visited = false;
- }
-
- 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;
-fail_link_loop: {
- char *npath = fstree_get_path(n);
- char *tpath = fstree_get_path(it);
- fprintf(stderr, "Hard link loop detected in '%s' -> '%s'\n",
- npath == NULL ? n->name : npath,
- tpath == NULL ? it->name : tpath);
- free(npath);
- free(tpath);
-}
- return -1;
-}
-
static file_info_t *file_list_dfs(tree_node_t *n)
{
if (S_ISREG(n->mode)) {
@@ -187,7 +142,7 @@ int fstree_post_process(fstree_t *fs)
{
size_t inum;
- if (resolve_hard_links_dfs(fs, fs->root))
+ if (fstree_resolve_hard_links(fs))
return -1;
fs->unique_inode_count = 0;