From c5f0334e87deea2b54f33f62ee879455a814633c Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 20 Apr 2023 14:08:34 +0200 Subject: libfstree: Remove special modes for hard links Instead of adding special sentinel modes, simply treat hard links as special case of symlinks, setting a flag to indicate that it is a hard link and another flag to indicate that it has been resolved. Signed-off-by: David Oberhollenzer --- include/fstree.h | 5 ++--- lib/common/src/writer/serialize_fstree.c | 3 ++- lib/fstree/src/hardlink.c | 13 +++++++------ lib/fstree/src/post_process.c | 25 ++++++++++++++----------- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/include/fstree.h b/include/fstree.h index 72cbc29..d08ccae 100644 --- a/include/fstree.h +++ b/include/fstree.h @@ -18,9 +18,6 @@ #include "io/istream.h" #include "compat.h" -#define FSTREE_MODE_HARD_LINK (0) -#define FSTREE_MODE_HARD_LINK_RESOLVED (1) - typedef struct fstree_defaults_t fstree_defaults_t; typedef struct tree_node_t tree_node_t; typedef struct fstree_t fstree_t; @@ -28,6 +25,8 @@ typedef struct fstree_t fstree_t; enum { FLAG_DIR_CREATED_IMPLICITLY = 0x01, FLAG_FILE_ALREADY_MATCHED = 0x02, + FLAG_LINK_IS_HARD = 0x04, + FLAG_LINK_RESOVED = 0x08, }; /* A node in a file system tree */ diff --git a/lib/common/src/writer/serialize_fstree.c b/lib/common/src/writer/serialize_fstree.c index 7ecd850..b5151f3 100644 --- a/lib/common/src/writer/serialize_fstree.c +++ b/lib/common/src/writer/serialize_fstree.c @@ -35,6 +35,7 @@ static sqfs_inode_generic_t *tree_node_to_inode(tree_node_t *node) inode->data.ipc.nlink = node->link_count; break; case S_IFLNK: + assert(!(node->flags & FLAG_LINK_IS_HARD)); inode->base.type = SQFS_INODE_SLINK; inode->data.slink.nlink = node->link_count; inode->data.slink.target_size = extra; @@ -71,7 +72,7 @@ static sqfs_inode_generic_t *write_dir_entries(const char *filename, goto fail; for (it = node->data.children; it != NULL; it = it->next) { - if (it->mode == FSTREE_MODE_HARD_LINK_RESOLVED) { + if (S_ISLNK(it->mode) && (it->flags & FLAG_LINK_IS_HARD)) { tgt = it->data.target_node; } else { tgt = it; diff --git a/lib/fstree/src/hardlink.c b/lib/fstree/src/hardlink.c index 81636c7..b6467e2 100644 --- a/lib/fstree/src/hardlink.c +++ b/lib/fstree/src/hardlink.c @@ -18,16 +18,17 @@ static int resolve_link(fstree_t *fs, tree_node_t *node) tree_node_t *start = node; for (;;) { - if (node->mode == FSTREE_MODE_HARD_LINK_RESOLVED) { + if (!S_ISLNK(node->mode) || !(node->flags & FLAG_LINK_IS_HARD)) + break; + + if (node->flags & FLAG_LINK_RESOVED) { node = node->data.target_node; - } else if (node->mode == FSTREE_MODE_HARD_LINK) { + } else { node = fstree_get_node_by_path(fs, fs->root, node->data.target, false, false); if (node == NULL) return -1; - } else { - break; } if (node == start) { @@ -46,7 +47,7 @@ static int resolve_link(fstree_t *fs, tree_node_t *node) return -1; } - start->mode = FSTREE_MODE_HARD_LINK_RESOLVED; + start->flags |= FLAG_LINK_RESOVED; start->data.target_node = node; node->link_count++; @@ -70,7 +71,7 @@ tree_node_t *fstree_add_hard_link(fstree_t *fs, const char *path, return NULL; } - n->mode = FSTREE_MODE_HARD_LINK; + n->flags |= FLAG_LINK_IS_HARD; } n->next_by_type = fs->links_unresolved; diff --git a/lib/fstree/src/post_process.c b/lib/fstree/src/post_process.c index f8bc0f7..c5a15a3 100644 --- a/lib/fstree/src/post_process.c +++ b/lib/fstree/src/post_process.c @@ -35,18 +35,19 @@ static int alloc_inode_num_dfs(fstree_t *fs, tree_node_t *root) } for (it = root->data.children; it != NULL; it = it->next) { - if (it->mode != FSTREE_MODE_HARD_LINK_RESOLVED) { - if (SZ_ADD_OV(fs->unique_inode_count, 1, &inum)) - goto fail_ov; + if (S_ISLNK(it->mode) && (it->flags & FLAG_LINK_IS_HARD)) + continue; - if ((sizeof(size_t) > sizeof(sqfs_u32)) && - inum > 0x0FFFFFFFFUL) { - goto fail_ov; - } + if (SZ_ADD_OV(fs->unique_inode_count, 1, &inum)) + goto fail_ov; - it->inode_num = (sqfs_u32)inum; - fs->unique_inode_count = inum; + if ((sizeof(size_t) > sizeof(sqfs_u32)) && + inum > 0x0FFFFFFFFUL) { + goto fail_ov; } + + it->inode_num = (sqfs_u32)inum; + fs->unique_inode_count = inum; } return 0; @@ -87,7 +88,7 @@ static tree_node_t *file_list_dfs(tree_node_t *n) static void map_inodes_dfs(fstree_t *fs, tree_node_t *n) { - if (n->mode == FSTREE_MODE_HARD_LINK_RESOLVED) + if (S_ISLNK(n->mode) && (n->flags & FLAG_LINK_IS_HARD)) return; fs->inodes[n->inode_num - 1] = n; @@ -110,7 +111,9 @@ static void reorder_hard_links(fstree_t *fs) it = fs->inodes[i]->data.children; for (; it != NULL; it = it->next) { - if (it->mode != FSTREE_MODE_HARD_LINK_RESOLVED) + if (!S_ISLNK(it->mode)) + continue; + if (!(it->flags & FLAG_LINK_IS_HARD)) continue; tgt = it->data.target_node; -- cgit v1.2.3