diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sqfs/dir_writer.c | 50 | ||||
-rw-r--r-- | lib/sqfshelper/serialize_fstree.c | 53 |
2 files changed, 85 insertions, 18 deletions
diff --git a/lib/sqfs/dir_writer.c b/lib/sqfs/dir_writer.c index d7bb590..47e6b62 100644 --- a/lib/sqfs/dir_writer.c +++ b/lib/sqfs/dir_writer.c @@ -45,6 +45,7 @@ struct sqfs_dir_writer_t { uint64_t dir_ref; size_t dir_size; size_t idx_size; + size_t ent_count; sqfs_meta_writer_t *dm; }; @@ -85,6 +86,7 @@ static void writer_reset(sqfs_dir_writer_t *writer) writer->dir_ref = 0; writer->dir_size = 0; writer->idx_size = 0; + writer->ent_count = 0; } sqfs_dir_writer_t *sqfs_dir_writer_create(sqfs_meta_writer_t *dm) @@ -145,6 +147,7 @@ int sqfs_dir_writer_add_entry(sqfs_dir_writer_t *writer, const char *name, } writer->dir_size += sizeof(ent) + ent->name_len; + writer->ent_count += 1; return 0; } @@ -275,6 +278,53 @@ size_t sqfs_dir_writer_get_index_size(const sqfs_dir_writer_t *writer) return writer->idx_size; } +size_t sqfs_dir_writer_get_entry_count(const sqfs_dir_writer_t *writer) +{ + return writer->ent_count; +} + +sqfs_inode_generic_t +*sqfs_dir_writer_create_inode(const sqfs_dir_writer_t *writer, + size_t hlinks, uint32_t xattr, + uint32_t parent_ino) +{ + sqfs_inode_generic_t *inode; + uint64_t start_block; + uint16_t block_offset; + + inode = calloc(1, sizeof(*inode)); + if (inode == NULL) + return NULL; + + start_block = writer->dir_ref >> 16; + block_offset = writer->dir_ref & 0xFFFF; + + if (xattr != 0xFFFFFFFF || start_block > 0xFFFFFFFFUL || + writer->dir_size > 0xFFFF) { + inode->base.type = SQFS_INODE_EXT_DIR; + } else { + inode->base.type = SQFS_INODE_DIR; + } + + if (inode->base.type == SQFS_INODE_DIR) { + inode->data.dir.start_block = start_block; + inode->data.dir.nlink = writer->ent_count + hlinks + 2; + inode->data.dir.size = writer->dir_size; + inode->data.dir.offset = block_offset; + inode->data.dir.parent_inode = parent_ino; + } else { + inode->data.dir_ext.nlink = writer->ent_count + hlinks + 2; + inode->data.dir_ext.size = writer->dir_size; + inode->data.dir_ext.start_block = start_block; + inode->data.dir_ext.parent_inode = parent_ino; + inode->data.dir_ext.offset = block_offset; + inode->data.dir_ext.xattr_idx = xattr; + inode->data.dir_ext.inodex_count = writer->idx_size; + } + + return inode; +} + int sqfs_dir_writer_write_index(const sqfs_dir_writer_t *writer, sqfs_meta_writer_t *im) { diff --git a/lib/sqfshelper/serialize_fstree.c b/lib/sqfshelper/serialize_fstree.c index 78f7d13..61f9ae2 100644 --- a/lib/sqfshelper/serialize_fstree.c +++ b/lib/sqfshelper/serialize_fstree.c @@ -14,31 +14,51 @@ #include <stdlib.h> #include <stdio.h> -static int write_dir_entries(sqfs_dir_writer_t *dirw, tree_node_t *node) +static sqfs_inode_generic_t *write_dir_entries(sqfs_dir_writer_t *dirw, + tree_node_t *node, + sqfs_id_table_t *idtbl) { + uint32_t xattr, parent_inode; + sqfs_inode_generic_t *inode; tree_node_t *it; - uint64_t ref; int ret; if (sqfs_dir_writer_begin(dirw)) - return -1; + return NULL; 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; + return NULL; } if (sqfs_dir_writer_end(dirw)) - return -1; + return NULL; + + xattr = (node->xattr == NULL) ? 0xFFFFFFFF : node->xattr->index; + parent_inode = (node->parent == NULL) ? 1 : node->parent->inode_num; + + inode = sqfs_dir_writer_create_inode(dirw, 0, xattr, parent_inode); + if (inode == NULL) { + perror("creating inode"); + return NULL; + } - ref = sqfs_dir_writer_get_dir_reference(dirw); + if (sqfs_id_table_id_to_index(idtbl, node->uid, &inode->base.uid_idx)) + goto fail_id; - 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; + if (sqfs_id_table_id_to_index(idtbl, node->gid, &inode->base.gid_idx)) + goto fail_id; + + inode->base.mode = node->mode; + inode->base.mod_time = node->mod_time; + inode->base.inode_number = node->inode_num; + return inode; +fail_id: + fputs("failed to allocate IDs\n", stderr); + free(inode); + return NULL; } int sqfs_serialize_fstree(sqfs_file_t *file, sqfs_super_t *super, fstree_t *fs, @@ -69,19 +89,16 @@ int sqfs_serialize_fstree(sqfs_file_t *file, sqfs_super_t *super, fstree_t *fs, for (i = 2; i < fs->inode_tbl_size; ++i) { if (S_ISDIR(fs->inode_table[i]->mode)) { - if (write_dir_entries(dirwr, fs->inode_table[i])) - goto out; + inode = write_dir_entries(dirwr, fs->inode_table[i], + idtbl); + } else { + inode = tree_node_to_inode(fs, idtbl, + fs->inode_table[i]); } - inode = tree_node_to_inode(fs, idtbl, fs->inode_table[i]); 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); - } - sqfs_meta_writer_get_position(im, &block, &offset); fs->inode_table[i]->inode_ref = (block << 16) | offset; |