diff options
-rw-r--r-- | include/fstree.h | 6 | ||||
-rw-r--r-- | lib/common/serialize_fstree.c | 45 | ||||
-rw-r--r-- | lib/fstree/fstree.c | 1 | ||||
-rw-r--r-- | lib/fstree/post_process.c | 27 |
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; } |