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 /lib/fstree/src | |
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>
Diffstat (limited to 'lib/fstree/src')
-rw-r--r-- | lib/fstree/src/hardlink.c | 99 | ||||
-rw-r--r-- | lib/fstree/src/post_process.c | 47 |
2 files changed, 76 insertions, 70 deletions
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; |