From cbdfa738c245019b7b711854d03f1ed87223ba49 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 28 May 2020 22:24:08 +0200 Subject: Turn the sqfs_block_writer_t into an interface This way, everything that could be done through the hooks (and more) can be done by simply providign a custom implementation. The result is a lot clener that the previous hook based version. Signed-off-by: David Oberhollenzer --- include/sqfs/block_writer.h | 95 +++++++++++++++++++++------------------ lib/common/statistics.c | 2 +- lib/sqfs/block_processor/common.c | 4 +- lib/sqfs/block_writer.c | 77 ++++++++++++++++--------------- 4 files changed, 94 insertions(+), 84 deletions(-) diff --git a/include/sqfs/block_writer.h b/include/sqfs/block_writer.h index 8cfb9a2..f8bc671 100644 --- a/include/sqfs/block_writer.h +++ b/include/sqfs/block_writer.h @@ -29,21 +29,69 @@ */ /** - * @struct sqfs_block_writer_t + * @interface sqfs_block_writer_t * * @implements sqfs_object_t * * @brief Abstracts writing and deduplicating of data and fragment blocks. * - * This object is not copyable, i.e. @ref sqfs_copy will always return NULL. + * A default reference implementation can be obtaiend + * through @ref sqfs_block_writer_create. The default implementation is not + * copyable, i.e. @ref sqfs_copy will always return NULL. */ +struct sqfs_block_writer_t { + sqfs_object_t base; + + /** + * @brief Submit a data block to a block writer. + * + * @memberof sqfs_block_writer_t + * + * If the @ref SQFS_BLK_FIRST_BLOCK flag is set, the data block writer + * memorizes the starting location and block index of the block. If the + * @ref SQFS_BLK_LAST_BLOCK flag is set, it uses those stored locations + * to do block deduplication. + * + * If the flag @ref SQFS_BLK_ALIGN is set in combination with the + * @ref SQFS_BLK_FIRST_BLOCK, the file size is padded to a multiple of + * the device block size before writing. If it is set together with the + * @ref SQFS_BLK_LAST_BLOCK flag, the padding is added afterwards. + * + * @param wr A pointer to a block writer. + * @param size The size of the block to write. + * @param checksum A 32 bit checksum of the block data. + * @param flags A combination of @ref SQFS_BLK_FLAGS flag bits + * describing the block. + * @arapm data A pointer to the data to write. + * @param location Returns the location where the block has been + * written. If the @ref SQFS_BLK_LAST_BLOCK flag was set, + * deduplication is performed and this returns the (new) location + * of the first block instead. + * + * @return Zero on success, an @ref SQFS_ERROR error on failure. + */ + int (*write_data_block)(sqfs_block_writer_t *wr, sqfs_u32 size, + sqfs_u32 checksum, sqfs_u32 flags, + const sqfs_u8 *data, sqfs_u64 *location); + + /** + * @brief Get the number of blocks actually written to disk. + * + * @memberof sqfs_block_writer_t + * + * @param wr A pointer to a block writer. + * + * @return The number of blocks written, excluding deduplicated blocks. + */ + sqfs_u64 (*get_block_count)(const sqfs_block_writer_t *wr); +}; #ifdef __cplusplus extern "C" { #endif /** - * @brief Create a block writer object. + * @brief Create an instance of a default block writer implementation. * * @memberof sqfs_block_writer_t * @@ -58,47 +106,6 @@ SQFS_API sqfs_block_writer_t *sqfs_block_writer_create(sqfs_file_t *file, size_t devblksz, sqfs_u32 flags); -/** - * @brief Submit a data block to a blokc writer. - * - * @memberof sqfs_block_writer_t - * - * If the @ref SQFS_BLK_FIRST_BLOCK flag is set, the data block writer - * memorizes the starting location and block index of the block. If the - * @ref SQFS_BLK_LAST_BLOCK flag is set, it uses those stored locations - * to do block deduplication. - * - * If the flag @ref SQFS_BLK_ALIGN is set in combination with the - * @ref SQFS_BLK_FIRST_BLOCK, the file size is padded to a multiple of the - * device block size before writing. If it is set together with the - * @ref SQFS_BLK_LAST_BLOCK flag, the padding is added afterwards. - * - * @param wr A pointer to a block writer. - * @param block The block to write to disk next. - * @param location Returns the location where the block has been written. - * If the @ref SQFS_BLK_LAST_BLOCK flag was set, deduplication - * is performed and this returns the (new) location of the - * first block instead. - * - * @return Zero on success, an @ref SQFS_ERROR error on failure. - */ -SQFS_API int sqfs_block_writer_write(sqfs_block_writer_t *wr, - sqfs_u32 size, sqfs_u32 checksum, - sqfs_u32 flags, const sqfs_u8 *data, - sqfs_u64 *location); - -/** - * @brief Get the number of blocks actually written to disk. - * - * @memberof sqfs_block_writer_t - * - * @param wr A pointer to a block writer. - * - * @return The number of blocks written, excluding deduplicated blocks. - */ -SQFS_API -sqfs_u64 sqfs_block_writer_get_block_count(const sqfs_block_writer_t *wr); - #ifdef __cplusplus } #endif diff --git a/lib/common/statistics.c b/lib/common/statistics.c index 079c1b1..82e545d 100644 --- a/lib/common/statistics.c +++ b/lib/common/statistics.c @@ -18,7 +18,7 @@ void sqfs_print_statistics(const sqfs_super_t *super, size_t ratio; proc_stats = sqfs_block_processor_get_stats(blk); - blocks_written = sqfs_block_writer_get_block_count(wr); + blocks_written = wr->get_block_count(wr); bytes_written = super->inode_table_start - sizeof(*super); diff --git a/lib/sqfs/block_processor/common.c b/lib/sqfs/block_processor/common.c index 757544a..e3d5486 100644 --- a/lib/sqfs/block_processor/common.c +++ b/lib/sqfs/block_processor/common.c @@ -68,8 +68,8 @@ int process_completed_block(sqfs_block_processor_t *proc, sqfs_block_t *blk) sqfs_u32 size; int err; - err = sqfs_block_writer_write(proc->wr, blk->size, blk->checksum, - blk->flags, blk->data, &location); + err = proc->wr->write_data_block(proc->wr, blk->size, blk->checksum, + blk->flags, blk->data, &location); if (err) goto out; diff --git a/lib/sqfs/block_writer.c b/lib/sqfs/block_writer.c index 06cbd37..a6ca4b3 100644 --- a/lib/sqfs/block_writer.c +++ b/lib/sqfs/block_writer.c @@ -25,8 +25,8 @@ typedef struct { sqfs_u64 hash; } blk_info_t; -struct sqfs_block_writer_t { - sqfs_object_t base; +typedef struct { + sqfs_block_writer_t base; sqfs_file_t *file; size_t num_blocks; @@ -39,9 +39,9 @@ struct sqfs_block_writer_t { sqfs_u64 start; size_t file_start; -}; +} block_writer_default_t; -static int store_block_location(sqfs_block_writer_t *wr, sqfs_u64 offset, +static int store_block_location(block_writer_default_t *wr, sqfs_u64 offset, sqfs_u32 size, sqfs_u32 chksum) { size_t new_sz; @@ -64,7 +64,7 @@ static int store_block_location(sqfs_block_writer_t *wr, sqfs_u64 offset, return 0; } -static size_t deduplicate_blocks(sqfs_block_writer_t *wr, size_t count) +static size_t deduplicate_blocks(block_writer_default_t *wr, size_t count) { size_t i, j; @@ -85,7 +85,7 @@ static size_t deduplicate_blocks(sqfs_block_writer_t *wr, size_t count) return i; } -static int align_file(sqfs_block_writer_t *wr) +static int align_file(block_writer_default_t *wr) { void *padding; sqfs_u64 size; @@ -111,41 +111,15 @@ static int align_file(sqfs_block_writer_t *wr) static void block_writer_destroy(sqfs_object_t *wr) { - free(((sqfs_block_writer_t *)wr)->blocks); + free(((block_writer_default_t *)wr)->blocks); free(wr); } -sqfs_block_writer_t *sqfs_block_writer_create(sqfs_file_t *file, - size_t devblksz, sqfs_u32 flags) -{ - sqfs_block_writer_t *wr; - - if (flags != 0) - return NULL; - - wr = calloc(1, sizeof(*wr)); - if (wr == NULL) - return NULL; - - ((sqfs_object_t *)wr)->destroy = block_writer_destroy; - wr->file = file; - wr->devblksz = devblksz; - wr->max_blocks = INIT_BLOCK_COUNT; - wr->data_area_start = wr->file->get_size(wr->file); - - wr->blocks = alloc_array(sizeof(wr->blocks[0]), wr->max_blocks); - if (wr->blocks == NULL) { - free(wr); - return NULL; - } - - return wr; -} - -int sqfs_block_writer_write(sqfs_block_writer_t *wr, sqfs_u32 size, +static int write_data_block(sqfs_block_writer_t *base, sqfs_u32 size, sqfs_u32 checksum, sqfs_u32 flags, const sqfs_u8 *data, sqfs_u64 *location) { + block_writer_default_t *wr = (block_writer_default_t *)base; size_t start, count; sqfs_u64 offset; sqfs_u32 out; @@ -219,7 +193,36 @@ int sqfs_block_writer_write(sqfs_block_writer_t *wr, sqfs_u32 size, return 0; } -sqfs_u64 sqfs_block_writer_get_block_count(const sqfs_block_writer_t *wr) +static sqfs_u64 get_block_count(const sqfs_block_writer_t *wr) { - return wr->blocks_written; + return ((const block_writer_default_t *)wr)->blocks_written; +} + +sqfs_block_writer_t *sqfs_block_writer_create(sqfs_file_t *file, + size_t devblksz, sqfs_u32 flags) +{ + block_writer_default_t *wr; + + if (flags != 0) + return NULL; + + wr = calloc(1, sizeof(*wr)); + if (wr == NULL) + return NULL; + + ((sqfs_block_writer_t *)wr)->write_data_block = write_data_block; + ((sqfs_block_writer_t *)wr)->get_block_count = get_block_count; + ((sqfs_object_t *)wr)->destroy = block_writer_destroy; + wr->file = file; + wr->devblksz = devblksz; + wr->max_blocks = INIT_BLOCK_COUNT; + wr->data_area_start = wr->file->get_size(wr->file); + + wr->blocks = alloc_array(sizeof(wr->blocks[0]), wr->max_blocks); + if (wr->blocks == NULL) { + free(wr); + return NULL; + } + + return (sqfs_block_writer_t *)wr; } -- cgit v1.2.3