summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fstree.h6
-rw-r--r--lib/common/serialize_fstree.c45
-rw-r--r--lib/fstree/fstree.c1
-rw-r--r--lib/fstree/post_process.c27
4 files changed, 34 insertions, 45 deletions
diff --git a/include/fstree.h b/include/fstree.h
index 7f81cf5..6628540 100644
--- a/include/fstree.h
+++ b/include/fstree.h
@@ -91,6 +91,9 @@ struct fstree_t {
struct stat defaults;
size_t unique_inode_count;
+ /* flat array of all nodes that have an inode number */
+ tree_node_t **inodes;
+
tree_node_t *root;
/* linear linked list of all regular files */
@@ -169,6 +172,9 @@ int fstree_from_file(fstree_t *fs, const char *filename, FILE *fp);
The total inode count is stored in unique_inode_count. The head of the file
list is pointed to by fs->files.
+ The "inodes" array is allocated and each node that has an inode number is
+ mapped into the array at index inode_num - 1.
+
Returns 0 on success, prints to stderr on failure.
*/
int fstree_post_process(fstree_t *fs);
diff --git a/lib/common/serialize_fstree.c b/lib/common/serialize_fstree.c
index a5f5d71..f20ae07 100644
--- a/lib/common/serialize_fstree.c
+++ b/lib/common/serialize_fstree.c
@@ -117,9 +117,6 @@ static int serialize_tree_node(const char *filename, sqfs_writer_t *wr,
sqfs_u64 block;
int ret;
- if (n->mode == FSTREE_MODE_HARD_LINK_RESOLVED)
- return 0;
-
if (S_ISDIR(n->mode)) {
inode = write_dir_entries(filename, wr->dirwr, n);
ret = SQFS_ERROR_INTERNAL;
@@ -167,55 +164,19 @@ out:
return ret;
}
-static int serialize_recursive(const char *filename, sqfs_writer_t *wr,
- tree_node_t *root)
-{
- bool has_subdirs = false;
- tree_node_t *it;
- int ret;
-
- for (it = root->data.dir.children; it != NULL; it = it->next) {
- if (S_ISDIR(it->mode)) {
- has_subdirs = true;
- break;
- }
- }
-
- if (has_subdirs) {
- for (it = root->data.dir.children; it != NULL; it = it->next) {
- if (S_ISDIR(it->mode)) {
- ret = serialize_recursive(filename, wr, it);
- if (ret)
- return ret;
- }
- }
- }
-
- for (it = root->data.dir.children; it != NULL; it = it->next) {
- ret = serialize_tree_node(filename, wr, it);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
int sqfs_serialize_fstree(const char *filename, sqfs_writer_t *wr)
{
+ size_t i;
int ret;
wr->super.inode_table_start = wr->outfile->get_size(wr->outfile);
- if (S_ISDIR(wr->fs.root->mode)) {
- ret = serialize_recursive(filename, wr, wr->fs.root);
+ for (i = 0; i < wr->fs.unique_inode_count; ++i) {
+ ret = serialize_tree_node(filename, wr, wr->fs.inodes[i]);
if (ret)
goto out;
}
- ret = serialize_tree_node(filename, wr, wr->fs.root);
- if (ret)
- goto out;
-
ret = sqfs_meta_writer_flush(wr->im);
if (ret)
goto out;
diff --git a/lib/fstree/fstree.c b/lib/fstree/fstree.c
index ce35b84..b2e199d 100644
--- a/lib/fstree/fstree.c
+++ b/lib/fstree/fstree.c
@@ -126,5 +126,6 @@ int fstree_init(fstree_t *fs, char *defaults)
void fstree_cleanup(fstree_t *fs)
{
free_recursive(fs->root);
+ free(fs->inodes);
memset(fs, 0, sizeof(*fs));
}
diff --git a/lib/fstree/post_process.c b/lib/fstree/post_process.c
index e6bcb3f..c2b462b 100644
--- a/lib/fstree/post_process.c
+++ b/lib/fstree/post_process.c
@@ -47,7 +47,7 @@ static void hard_link_snap(tree_node_t *n)
n->data.target_node = n->data.target_node->data.target_node;
}
-static int map_child_nodes(fstree_t *fs, tree_node_t *root, size_t *counter)
+static int alloc_inode_num_dfs(fstree_t *fs, tree_node_t *root, size_t *counter)
{
bool has_subdirs = false;
tree_node_t *it, *tgt;
@@ -68,7 +68,7 @@ static int map_child_nodes(fstree_t *fs, tree_node_t *root, size_t *counter)
if (has_subdirs) {
for (it = root->data.dir.children; it != NULL; it = it->next) {
if (S_ISDIR(it->mode)) {
- if (map_child_nodes(fs, it, counter))
+ if (alloc_inode_num_dfs(fs, it, counter))
return -1;
}
}
@@ -172,6 +172,19 @@ static file_info_t *file_list_dfs(tree_node_t *n)
return NULL;
}
+static void map_inodes_dfs(fstree_t *fs, tree_node_t *n)
+{
+ if (n->mode == FSTREE_MODE_HARD_LINK_RESOLVED)
+ return;
+
+ fs->inodes[n->inode_num - 1] = n;
+
+ if (S_ISDIR(n->mode)) {
+ for (n = n->data.dir.children; n != NULL; n = n->next)
+ map_inodes_dfs(fs, n);
+ }
+}
+
int fstree_post_process(fstree_t *fs)
{
size_t inum = 1;
@@ -182,11 +195,19 @@ int fstree_post_process(fstree_t *fs)
return -1;
fs->unique_inode_count = 0;
- if (map_child_nodes(fs, fs->root, &inum))
+ if (alloc_inode_num_dfs(fs, fs->root, &inum))
return -1;
fs->root->inode_num = inum;
fs->unique_inode_count += 1;
+ fs->inodes = calloc(sizeof(fs->inodes[0]), fs->unique_inode_count);
+ if (fs->inodes == NULL) {
+ perror("Allocating inode list");
+ return -1;
+ }
+
+ map_inodes_dfs(fs, fs->root);
+
fs->files = file_list_dfs(fs->root);
return 0;
}