diff options
Diffstat (limited to 'lib/sqfshelper/serialize_fstree.c')
-rw-r--r-- | lib/sqfshelper/serialize_fstree.c | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/lib/sqfshelper/serialize_fstree.c b/lib/sqfshelper/serialize_fstree.c index 53e2236..f8f3913 100644 --- a/lib/sqfshelper/serialize_fstree.c +++ b/lib/sqfshelper/serialize_fstree.c @@ -11,17 +11,46 @@ #include "util.h" #include <unistd.h> +#include <stdlib.h> #include <stdio.h> +static int write_dir_entries(sqfs_dir_writer_t *dirw, tree_node_t *node) +{ + tree_node_t *it; + uint64_t ref; + int ret; + + if (sqfs_dir_writer_begin(dirw)) + return -1; + + for (it = node->data.dir->children; it != NULL; it = it->next) { + ret = sqfs_dir_writer_add_entry(dirw, it->name, it->inode_num, + it->inode_ref, it->mode); + if (ret) + return -1; + } + + if (sqfs_dir_writer_end(dirw)) + return -1; + + ref = sqfs_dir_writer_get_dir_reference(dirw); + + node->data.dir->size = sqfs_dir_writer_get_size(dirw); + node->data.dir->start_block = ref >> 16; + node->data.dir->block_offset = ref & 0xFFFF; + return 0; +} + int sqfs_serialize_fstree(int outfd, sqfs_super_t *super, fstree_t *fs, compressor_t *cmp, id_table_t *idtbl) { + sqfs_inode_generic_t *inode; sqfs_dir_writer_t *dirwr; meta_writer_t *im, *dm; + size_t i, count; uint32_t offset; uint64_t block; int ret = -1; - size_t i; im = meta_writer_create(outfd, cmp, false); if (im == NULL) @@ -36,10 +65,37 @@ int sqfs_serialize_fstree(int outfd, sqfs_super_t *super, fstree_t *fs, goto out_dm; for (i = 2; i < fs->inode_tbl_size; ++i) { - if (meta_writer_write_inode(fs, idtbl, im, dirwr, - fs->inode_table[i])) { + if (S_ISDIR(fs->inode_table[i]->mode)) { + if (write_dir_entries(dirwr, fs->inode_table[i])) + goto out; + } + + inode = tree_node_to_inode(fs, idtbl, fs->inode_table[i], + &count); + if (inode == NULL) + goto out; + + if (inode->base.type == SQFS_INODE_EXT_DIR) { + inode->data.dir_ext.inodex_count = + sqfs_dir_writer_get_index_size(dirwr); + } + + meta_writer_get_position(im, &block, &offset); + fs->inode_table[i]->inode_ref = (block << 16) | offset; + + if (meta_writer_write_inode(im, inode, count)) { + free(inode); goto out; } + + if (inode->base.type == SQFS_INODE_EXT_DIR) { + if (sqfs_dir_writer_write_index(dirwr, im)) { + free(inode); + goto out; + } + } + + free(inode); } if (meta_writer_flush(im)) |