aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fstree.h5
-rw-r--r--lib/common/src/writer/serialize_fstree.c3
-rw-r--r--lib/fstree/src/hardlink.c13
-rw-r--r--lib/fstree/src/post_process.c25
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;