diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-04-06 14:53:49 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-04-06 18:07:59 +0200 |
commit | c42e4fbbc6b175f843c4d0eeaaa9ead2d0e746b6 (patch) | |
tree | adf2e61d9acdf5e18321d6ba0277dd3428de8fe3 | |
parent | 23fab1d2b8164a99c5536581bb80769a620c65c0 (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.h | 4 | ||||
-rw-r--r-- | lib/fstree/src/hardlink.c | 99 | ||||
-rw-r--r-- | lib/fstree/src/post_process.c | 47 |
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; |