From c92faad51817c10570de3680e95a3fd18bb21204 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sun, 12 Jan 2020 08:15:00 +0100 Subject: Add an inode deep copy helper function to libsquashfs Signed-off-by: David Oberhollenzer --- include/sqfs/inode.h | 18 ++++++++++++++++++ lib/sqfs/inode.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/sqfs/inode.h b/include/sqfs/inode.h index 336a394..2b4a550 100644 --- a/include/sqfs/inode.h +++ b/include/sqfs/inode.h @@ -536,6 +536,24 @@ struct sqfs_inode_generic_t { extern "C" { #endif +/** + * @brief Create a deep copy of a generic inode. + * + * The @ref sqfs_inode_generic_t structure contains inlined fields that have a + * size depending on the inode data and pointers to the inlined fields. This + * helper function calculates the actual size of the structure in memory, makes + * a copy and propperly sets up the pointers. + * + * @param src The inode to copy. + * @param copy Returns a pointer to the copy on success. Can be released with a + * single free call. + * + * @return Zero on success, an @ref SQFS_ERROR_CORRUPTED if the node has + * an unknown type set. + */ +SQFS_API int sqfs_inode_copy(const sqfs_inode_generic_t *src, + sqfs_inode_generic_t **copy); + /** * @brief Get the extended attribute index of an inode * diff --git a/lib/sqfs/inode.c b/lib/sqfs/inode.c index 4a75e64..bb1ccef 100644 --- a/lib/sqfs/inode.c +++ b/lib/sqfs/inode.c @@ -10,6 +10,9 @@ #include "sqfs/inode.h" #include "sqfs/error.h" +#include +#include + static int inverse_type[] = { [SQFS_INODE_DIR] = SQFS_INODE_EXT_DIR, [SQFS_INODE_FILE] = SQFS_INODE_EXT_FILE, @@ -27,6 +30,52 @@ static int inverse_type[] = { [SQFS_INODE_EXT_SOCKET] = SQFS_INODE_SOCKET, }; +int sqfs_inode_copy(const sqfs_inode_generic_t *src, + sqfs_inode_generic_t **out) +{ + sqfs_inode_generic_t *copy; + size_t size = sizeof(*src); + + switch (src->base.type) { + case SQFS_INODE_FILE: + case SQFS_INODE_EXT_FILE: + size += src->num_file_blocks; + break; + case SQFS_INODE_DIR: + case SQFS_INODE_EXT_DIR: + size += src->num_dir_idx_bytes; + break; + case SQFS_INODE_SLINK: + size += src->data.slink.target_size; + break; + case SQFS_INODE_EXT_SLINK: + size += src->data.slink_ext.target_size; + break; + case SQFS_INODE_BDEV: + case SQFS_INODE_CDEV: + case SQFS_INODE_FIFO: + case SQFS_INODE_SOCKET: + case SQFS_INODE_EXT_BDEV: + case SQFS_INODE_EXT_CDEV: + case SQFS_INODE_EXT_FIFO: + case SQFS_INODE_EXT_SOCKET: + break; + default: + return SQFS_ERROR_CORRUPTED; + } + + copy = calloc(1, size); + if (copy == NULL) + return SQFS_ERROR_ALLOC; + + memcpy(copy, src, size); + copy->block_sizes = (sqfs_u32 *)copy->extra; + copy->slink_target = (char *)copy->extra; + + *out = copy; + return 0; +} + int sqfs_inode_get_xattr_index(const sqfs_inode_generic_t *inode, sqfs_u32 *out) { -- cgit v1.2.3