From a4d371f85ff05c99ce20b7ec49df15cfec11d915 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Tue, 19 Sep 2023 18:43:10 +0200 Subject: libsqfs: Add a helper function for turning an inode into a dir entry Signed-off-by: David Oberhollenzer --- include/sqfs/inode.h | 17 +++++++++++++ lib/sqfs/src/dir_iterator.c | 62 ++++----------------------------------------- lib/sqfs/src/inode.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 57 deletions(-) diff --git a/include/sqfs/inode.h b/include/sqfs/inode.h index 7f4e7b5..ba9c227 100644 --- a/include/sqfs/inode.h +++ b/include/sqfs/inode.h @@ -741,6 +741,23 @@ int sqfs_inode_unpack_dir_index_entry(const sqfs_inode_generic_t *inode, sqfs_dir_index_t **out, size_t index); +/** + * @brief Create a directory entry from an inode + * + * @param name The file name or path to store in the directory entry + * @param len The lengh of the file name, or 0 to use strlen internally + * @param inode The inode from which to use the data + * @param idtbl An ID table to use for resolving the inodes uid & gid + * @param out Returns a pointer to a @ref sqfs_dir_entry_t on success + * + * @return Zero on success, a negative @ref SQFS_ERROR value on failure + */ +SQFS_API +int sqfs_dir_entry_from_inode(const char *name, size_t len, + const sqfs_inode_generic_t *inode, + const sqfs_id_table_t *idtbl, + sqfs_dir_entry_t **out); + #ifdef __cplusplus } #endif diff --git a/lib/sqfs/src/dir_iterator.c b/lib/sqfs/src/dir_iterator.c index 3e1f63a..32612cf 100644 --- a/lib/sqfs/src/dir_iterator.c +++ b/lib/sqfs/src/dir_iterator.c @@ -39,7 +39,6 @@ static int it_next(sqfs_dir_iterator_t *base, sqfs_dir_entry_t **out) { iterator_t *it = (iterator_t *)base; sqfs_dir_entry_t *ent = NULL; - sqfs_u32 uid, gid; int ret; sqfs_free(it->inode); @@ -55,65 +54,14 @@ static int it_next(sqfs_dir_iterator_t *base, sqfs_dir_entry_t **out) if (ret != 0) goto fail; - ret = SQFS_ERROR_ALLOC; - ent = alloc_flex(sizeof(*ent), 1, it->dent->size + 2); - if (ent == NULL) + ret = sqfs_dir_entry_from_inode((const char *)it->dent->name, + it->dent->size + 1, it->inode, + it->id, &ent); + if (ret) goto fail; - ret = SQFS_ERROR_CORRUPTED; - if (sqfs_id_table_index_to_id(it->id, it->inode->base.uid_idx, &uid)) - goto fail; - - if (sqfs_id_table_index_to_id(it->id, it->inode->base.gid_idx, &gid)) - goto fail; - - memcpy(ent->name, it->dent->name, it->dent->size + 1); - - ent->mode = it->inode->base.mode; - ent->mtime = it->inode->base.mod_time; - ent->uid = uid; - ent->gid = gid; ent->inode = it->state.ent_ref; - it->xattr_idx = 0xFFFFFFFF; - - switch (it->inode->base.type) { - case SQFS_INODE_BDEV: - case SQFS_INODE_CDEV: - ent->rdev = it->inode->data.dev.devno; - break; - case SQFS_INODE_EXT_BDEV: - case SQFS_INODE_EXT_CDEV: - ent->rdev = it->inode->data.dev_ext.devno; - it->xattr_idx = it->inode->data.dev_ext.xattr_idx; - break; - case SQFS_INODE_FILE: - ent->size = it->inode->data.file.file_size; - break; - case SQFS_INODE_EXT_FILE: - ent->size = it->inode->data.file_ext.file_size; - it->xattr_idx = it->inode->data.file_ext.xattr_idx; - break; - case SQFS_INODE_DIR: - ent->size = it->inode->data.dir.size; - break; - case SQFS_INODE_EXT_DIR: - ent->size = it->inode->data.dir_ext.size; - it->xattr_idx = it->inode->data.dir_ext.xattr_idx; - break; - case SQFS_INODE_SLINK: - ent->size = it->inode->data.slink.target_size; - break; - case SQFS_INODE_EXT_SLINK: - ent->size = it->inode->data.slink_ext.target_size; - it->xattr_idx = it->inode->data.slink_ext.xattr_idx; - break; - case SQFS_INODE_EXT_FIFO: - case SQFS_INODE_EXT_SOCKET: - it->xattr_idx = it->inode->data.ipc_ext.xattr_idx; - break; - default: - break; - } + sqfs_inode_get_xattr_index(it->inode, &it->xattr_idx); *out = ent; return 0; diff --git a/lib/sqfs/src/inode.c b/lib/sqfs/src/inode.c index ce51cf5..4966126 100644 --- a/lib/sqfs/src/inode.c +++ b/lib/sqfs/src/inode.c @@ -7,6 +7,8 @@ #define SQFS_BUILDING_DLL #include "config.h" +#include "sqfs/dir_entry.h" +#include "sqfs/id_table.h" #include "sqfs/inode.h" #include "sqfs/error.h" #include "sqfs/dir.h" @@ -378,3 +380,63 @@ int sqfs_inode_unpack_dir_index_entry(const sqfs_inode_generic_t *inode, memcpy((*out)->name, ptr + offset + sizeof(ent), ent.size + 1); return 0; } + +int sqfs_dir_entry_from_inode(const char *name, size_t len, + const sqfs_inode_generic_t *inode, + const sqfs_id_table_t *idtbl, + sqfs_dir_entry_t **out) +{ + sqfs_dir_entry_t *ent; + sqfs_u32 uid, gid; + + if (sqfs_id_table_index_to_id(idtbl, inode->base.uid_idx, &uid)) + return SQFS_ERROR_CORRUPTED; + + if (sqfs_id_table_index_to_id(idtbl, inode->base.gid_idx, &gid)) + return SQFS_ERROR_CORRUPTED; + + len = len > 0 ? strnlen(name, len) : strlen(name); + ent = alloc_flex(sizeof(*ent), 1, len + 1); + if (ent == NULL) + return SQFS_ERROR_ALLOC; + + memcpy(ent->name, name, len); + ent->mode = inode->base.mode; + ent->mtime = inode->base.mod_time; + ent->uid = uid; + ent->gid = gid; + + switch (inode->base.type) { + case SQFS_INODE_BDEV: + case SQFS_INODE_CDEV: + ent->rdev = inode->data.dev.devno; + break; + case SQFS_INODE_EXT_BDEV: + case SQFS_INODE_EXT_CDEV: + ent->rdev = inode->data.dev_ext.devno; + break; + case SQFS_INODE_FILE: + ent->size = inode->data.file.file_size; + break; + case SQFS_INODE_EXT_FILE: + ent->size = inode->data.file_ext.file_size; + break; + case SQFS_INODE_DIR: + ent->size = inode->data.dir.size; + break; + case SQFS_INODE_EXT_DIR: + ent->size = inode->data.dir_ext.size; + break; + case SQFS_INODE_SLINK: + ent->size = inode->data.slink.target_size; + break; + case SQFS_INODE_EXT_SLINK: + ent->size = inode->data.slink_ext.target_size; + break; + default: + break; + } + + *out = ent; + return 0; +} -- cgit v1.2.3