diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-10-03 12:11:51 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-10-03 14:57:47 +0200 |
commit | 6a218f0927c0cced058e14ee5156f10860a149d3 (patch) | |
tree | edc56ce26501ee3cb47ed335922be22efc4843ef | |
parent | 9ffad2478a04011805132750644eabcb7f0c0e92 (diff) |
Store directory index in generic inode structure
This commit modifies the dir writer to store the directory index directly
in the payload area of the inode it creates. The size of the index in bytes
is stored in a seperate field. Storing the index is moved to the write
inode function.
The read inode function is in turn also modified to read the directory
index from disk and actually store it in the inode structure in memory
for later use.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | include/sqfs/dir_writer.h | 14 | ||||
-rw-r--r-- | include/sqfs/inode.h | 6 | ||||
-rw-r--r-- | lib/sqfs/dir_writer.c | 40 | ||||
-rw-r--r-- | lib/sqfs/read_inode.c | 91 | ||||
-rw-r--r-- | lib/sqfs/write_inode.c | 41 | ||||
-rw-r--r-- | lib/sqfshelper/serialize_fstree.c | 7 |
6 files changed, 140 insertions, 59 deletions
diff --git a/include/sqfs/dir_writer.h b/include/sqfs/dir_writer.h index b47628b..bb09a86 100644 --- a/include/sqfs/dir_writer.h +++ b/include/sqfs/dir_writer.h @@ -192,20 +192,6 @@ sqfs_dir_writer_get_dir_reference(const sqfs_dir_writer_t *writer); SQFS_API size_t sqfs_dir_writer_get_index_size(const sqfs_dir_writer_t *writer); /** - * @brief Write the index of the index of the last written directory to - * a meta data writer after the extended directory inode. - * - * @memberof sqfs_dir_writer_t - * - * @param writer A pointer to a directory writer object. - * @param im A pointer to a meta data writer to write the index to. - * - * @return Zero on success, a @ref E_SQFS_ERROR value on failure. - */ -SQFS_API int sqfs_dir_writer_write_index(const sqfs_dir_writer_t *writer, - sqfs_meta_writer_t *im); - -/** * @brief Helper function for creating an inode from the last directory. * * @memberof sqfs_dir_writer_t diff --git a/include/sqfs/inode.h b/include/sqfs/inode.h index f04f036..8b69b7e 100644 --- a/include/sqfs/inode.h +++ b/include/sqfs/inode.h @@ -505,6 +505,12 @@ struct sqfs_inode_generic_t { size_t num_file_blocks; /** + * @brief For extended directory inodes, stores the number of payload + * bytes following for the directory index. + */ + size_t num_dir_idx_bytes; + + /** * @brief Type specific inode data. */ union { diff --git a/lib/sqfs/dir_writer.c b/lib/sqfs/dir_writer.c index 5b8f6b1..a4aebe6 100644 --- a/lib/sqfs/dir_writer.c +++ b/lib/sqfs/dir_writer.c @@ -291,10 +291,13 @@ sqfs_inode_generic_t sqfs_u32 parent_ino) { sqfs_inode_generic_t *inode; + sqfs_dir_index_t *ent; sqfs_u64 start_block; sqfs_u16 block_offset; + index_ent_t *idx; + sqfs_u8 *ptr; - inode = calloc(1, sizeof(*inode)); + inode = alloc_flex(sizeof(*inode), 1, writer->idx_size); if (inode == NULL) return NULL; @@ -323,32 +326,21 @@ sqfs_inode_generic_t inode->data.dir_ext.xattr_idx = xattr; inode->data.dir_ext.inodex_count = writer->idx_size ? (writer->idx_size - 1) : 0; - } - - return inode; -} - -int sqfs_dir_writer_write_index(const sqfs_dir_writer_t *writer, - sqfs_meta_writer_t *im) -{ - sqfs_dir_index_t ent; - index_ent_t *idx; - int err; - for (idx = writer->idx; idx != NULL; idx = idx->next) { - ent.start_block = htole32(idx->block); - ent.index = htole32(idx->index); - ent.size = htole32(idx->ent->name_len - 1); + inode->num_dir_idx_bytes = writer->idx_size; + ptr = inode->extra; - err = sqfs_meta_writer_append(im, &ent, sizeof(ent)); - if (err) - return err; + for (idx = writer->idx; idx != NULL; idx = idx->next) { + ent = (sqfs_dir_index_t *)ptr; + ent->start_block = idx->block; + ent->index = idx->index; + ent->size = idx->ent->name_len - 1; - err = sqfs_meta_writer_append(im, idx->ent->name, - idx->ent->name_len); - if (err) - return err; + ptr += sizeof(*ent); + memcpy(ptr, idx->ent->name, idx->ent->name_len); + ptr += idx->ent->name_len; + } } - return 0; + return inode; } diff --git a/lib/sqfs/read_inode.c b/lib/sqfs/read_inode.c index 2887959..f877da1 100644 --- a/lib/sqfs/read_inode.c +++ b/lib/sqfs/read_inode.c @@ -11,9 +11,11 @@ #include "sqfs/error.h" #include "sqfs/super.h" #include "sqfs/inode.h" +#include "sqfs/dir.h" #include "util.h" #include <stdlib.h> +#include <string.h> #include <errno.h> #define SWAB16(x) x = le16toh(x) @@ -222,6 +224,80 @@ static int read_inode_slink_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base, return 0; } +static int read_inode_dir_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base, + sqfs_inode_generic_t **result) +{ + size_t i, new_sz, index_max, index_used; + sqfs_inode_generic_t *out; + sqfs_inode_dir_ext_t dir; + sqfs_dir_index_t ent; + void *new; + int err; + + err = sqfs_meta_reader_read(ir, &dir, sizeof(dir)); + if (err) + return err; + + SWAB32(dir.nlink); + SWAB32(dir.size); + SWAB32(dir.start_block); + SWAB32(dir.parent_inode); + SWAB16(dir.inodex_count); + SWAB16(dir.offset); + SWAB32(dir.xattr_idx); + + index_max = dir.size ? 128 : 0; + index_used = 0; + + out = alloc_flex(sizeof(*out), 1, index_max); + if (out == NULL) + return SQFS_ERROR_ALLOC; + + out->base = *base; + out->data.dir_ext = dir; + + if (dir.size == 0) { + *result = out; + return 0; + } + + for (i = 0; i <= dir.inodex_count; ++i) { + err = sqfs_meta_reader_read(ir, &ent, sizeof(ent)); + if (err) + return err; + + SWAB32(ent.start_block); + SWAB32(ent.index); + SWAB32(ent.size); + + new_sz = index_max; + while (sizeof(ent) + ent.size + 1 > new_sz - index_used) + new_sz *= 2; + + if (new_sz > index_max) { + new = realloc(out, sizeof(*out) + new_sz); + if (new == NULL) { + free(out); + return SQFS_ERROR_ALLOC; + } + out = new; + index_max = new_sz; + } + + memcpy(out->extra + index_used, &ent, sizeof(ent)); + index_used += sizeof(ent); + + err = sqfs_meta_reader_read(ir, out->extra + index_used, + ent.size + 1); + if (err) + return err; + } + + out->num_dir_idx_bytes = index_used; + *result = out; + return 0; +} + int sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, const sqfs_super_t *super, sqfs_u64 block_start, size_t offset, @@ -264,6 +340,8 @@ int sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, result); case SQFS_INODE_EXT_SLINK: return read_inode_slink_ext(ir, &inode, result); + case SQFS_INODE_EXT_DIR: + return read_inode_dir_ext(ir, &inode, result); default: break; } @@ -305,19 +383,6 @@ int sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, goto fail_free; SWAB32(out->data.ipc.nlink); break; - case SQFS_INODE_EXT_DIR: - err = sqfs_meta_reader_read(ir, &out->data.dir_ext, - sizeof(out->data.dir_ext)); - if (err) - goto fail_free; - SWAB32(out->data.dir_ext.nlink); - SWAB32(out->data.dir_ext.size); - SWAB32(out->data.dir_ext.start_block); - SWAB32(out->data.dir_ext.parent_inode); - SWAB16(out->data.dir_ext.inodex_count); - SWAB16(out->data.dir_ext.offset); - SWAB32(out->data.dir_ext.xattr_idx); - break; case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: err = sqfs_meta_reader_read(ir, &out->data.dev_ext, diff --git a/lib/sqfs/write_inode.c b/lib/sqfs/write_inode.c index af6b1e6..2e69b80 100644 --- a/lib/sqfs/write_inode.c +++ b/lib/sqfs/write_inode.c @@ -10,6 +10,7 @@ #include "sqfs/meta_writer.h" #include "sqfs/error.h" #include "sqfs/inode.h" +#include "sqfs/dir.h" #include "compat.h" static int write_block_sizes(sqfs_meta_writer_t *ir, @@ -25,6 +26,41 @@ static int write_block_sizes(sqfs_meta_writer_t *ir, sizeof(sqfs_u32) * n->num_file_blocks); } +static int write_dir_index(sqfs_meta_writer_t *ir, const sqfs_u8 *data, + size_t count) +{ + sqfs_dir_index_t *ent, copy; + size_t len; + int err; + + while (count > sizeof(*ent)) { + ent = (sqfs_dir_index_t *)data; + data += sizeof(*ent); + count -= sizeof(*ent); + len = ent->size + 1; + + if (len > count) + return SQFS_ERROR_CORRUPTED; + + copy.start_block = htole32(ent->start_block); + copy.index = htole32(ent->index); + copy.size = htole32(ent->size); + + err = sqfs_meta_writer_append(ir, ©, sizeof(copy)); + if (err) + return err; + + err = sqfs_meta_writer_append(ir, data, len); + if (err) + return err; + + data += len; + count -= len; + } + + return 0; +} + int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, const sqfs_inode_generic_t *n) { @@ -102,7 +138,10 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, .offset = htole16(n->data.dir_ext.offset), .xattr_idx = htole32(n->data.dir_ext.xattr_idx), }; - return sqfs_meta_writer_append(ir, &dir, sizeof(dir)); + ret = sqfs_meta_writer_append(ir, &dir, sizeof(dir)); + if (ret) + return ret; + return write_dir_index(ir, n->extra, n->num_dir_idx_bytes); } case SQFS_INODE_EXT_FILE: { sqfs_inode_file_ext_t file = { diff --git a/lib/sqfshelper/serialize_fstree.c b/lib/sqfshelper/serialize_fstree.c index 88305e7..854231c 100644 --- a/lib/sqfshelper/serialize_fstree.c +++ b/lib/sqfshelper/serialize_fstree.c @@ -106,13 +106,6 @@ int sqfs_serialize_fstree(sqfs_file_t *file, sqfs_super_t *super, fstree_t *fs, goto out; } - if (inode->base.type == SQFS_INODE_EXT_DIR) { - if (sqfs_dir_writer_write_index(dirwr, im)) { - free(inode); - goto out; - } - } - free(inode); } |