diff options
-rw-r--r-- | include/sqfs/data_writer.h | 19 | ||||
-rw-r--r-- | lib/sqfs/data_writer/common.c | 1 | ||||
-rw-r--r-- | lib/sqfs/data_writer/fileapi.c | 78 | ||||
-rw-r--r-- | lib/sqfs/data_writer/internal.h | 2 | ||||
-rw-r--r-- | lib/sqfshelper/data_writer.c | 19 |
5 files changed, 73 insertions, 46 deletions
diff --git a/include/sqfs/data_writer.h b/include/sqfs/data_writer.h index ffa3334..37d5479 100644 --- a/include/sqfs/data_writer.h +++ b/include/sqfs/data_writer.h @@ -173,23 +173,8 @@ SQFS_API int sqfs_data_writer_begin_file(sqfs_data_writer_t *proc, sqfs_inode_generic_t *inode, uint32_t flags); -/** - * @brief Add a block to be processed. - * - * @memberof sqfs_data_writer_t - * - * The function takes over ownership of the submitted block. It is freed after - * processing is done and it is written to disk. - * - * @param proc A pointer to a data writer object. - * @param block A pointer to a block to enqueue. - * - * @return Zero on success, an @ref E_SQFS_ERROR value on failure. Depending on - * the implementation used, the failure could have been caused by - * processing of a block that was submitted earlier. - */ -SQFS_API int sqfs_data_writer_enqueue(sqfs_data_writer_t *proc, - sqfs_block_t *block); +SQFS_API int sqfs_data_writer_append(sqfs_data_writer_t *proc, + const void *data, size_t size); SQFS_API int sqfs_data_writer_end_file(sqfs_data_writer_t *proc); diff --git a/lib/sqfs/data_writer/common.c b/lib/sqfs/data_writer/common.c index c9d5589..9e11e36 100644 --- a/lib/sqfs/data_writer/common.c +++ b/lib/sqfs/data_writer/common.c @@ -47,6 +47,7 @@ void data_writer_cleanup(sqfs_data_writer_t *proc) { free_blk_list(proc->queue); free_blk_list(proc->done); + free(proc->blk_current); free(proc->frag_block); free(proc->frag_list); free(proc->fragments); diff --git a/lib/sqfs/data_writer/fileapi.c b/lib/sqfs/data_writer/fileapi.c index b78d012..712fd29 100644 --- a/lib/sqfs/data_writer/fileapi.c +++ b/lib/sqfs/data_writer/fileapi.c @@ -35,16 +35,14 @@ int sqfs_data_writer_begin_file(sqfs_data_writer_t *proc, return test_and_set_status(proc, SQFS_ERROR_UNSUPPORTED); proc->inode = inode; - proc->blk_flags = flags; + proc->blk_flags = flags | SQFS_BLK_FIRST_BLOCK; proc->blk_index = 0; - proc->had_fragment = false; + proc->blk_current = NULL; return 0; } -int sqfs_data_writer_enqueue(sqfs_data_writer_t *proc, sqfs_block_t *block) +static int flush_block(sqfs_data_writer_t *proc, sqfs_block_t *block) { - int err; - block->index = proc->blk_index++; block->flags = proc->blk_flags; block->inode = proc->inode; @@ -59,25 +57,63 @@ int sqfs_data_writer_enqueue(sqfs_data_writer_t *proc, sqfs_block_t *block) } if (block->size < proc->max_block_size) { - if (block->index > 0) { - err = add_sentinel_block(proc); + block->flags |= SQFS_BLK_IS_FRAGMENT; + } else { + proc->inode->num_file_blocks += 1; + proc->blk_flags &= ~SQFS_BLK_FIRST_BLOCK; + } + + return data_writer_enqueue(proc, block); +} + +int sqfs_data_writer_append(sqfs_data_writer_t *proc, const void *data, + size_t size) +{ + size_t diff; + void *new; + int err; + + while (size > 0) { + if (proc->blk_current == NULL) { + new = alloc_flex(sizeof(*proc->blk_current), 1, + proc->max_block_size); + + if (new == NULL) + return test_and_set_status(proc, + SQFS_ERROR_ALLOC); - if (err) { - free(block); + proc->blk_current = new; + } + + diff = proc->max_block_size - proc->blk_current->size; + + if (diff == 0) { + err = flush_block(proc, proc->blk_current); + proc->blk_current = NULL; + if (err) return err; - } + continue; } - proc->had_fragment = true; - block->flags |= SQFS_BLK_IS_FRAGMENT; - } else { - if (block->index == 0) - block->flags |= SQFS_BLK_FIRST_BLOCK; + if (diff > size) + diff = size; - proc->inode->num_file_blocks += 1; + memcpy(proc->blk_current->data + proc->blk_current->size, + data, diff); + + size -= diff; + proc->blk_current->size += diff; + data = (const char *)data + diff; } - return data_writer_enqueue(proc, block); + if (proc->blk_current != NULL && + proc->blk_current->size == proc->max_block_size) { + err = flush_block(proc, proc->blk_current); + proc->blk_current = NULL; + return err; + } + + return 0; } int sqfs_data_writer_end_file(sqfs_data_writer_t *proc) @@ -87,15 +123,19 @@ int sqfs_data_writer_end_file(sqfs_data_writer_t *proc) if (proc->inode == NULL) return test_and_set_status(proc, SQFS_ERROR_INTERNAL); - if (!proc->had_fragment && proc->inode->num_file_blocks > 0) { + if (!(proc->blk_flags & SQFS_BLK_FIRST_BLOCK)) { err = add_sentinel_block(proc); if (err) return err; } + if (proc->blk_current != NULL) { + err = flush_block(proc, proc->blk_current); + proc->blk_current = NULL; + } + proc->inode = NULL; proc->blk_flags = 0; proc->blk_index = 0; - proc->had_fragment = false; return 0; } diff --git a/lib/sqfs/data_writer/internal.h b/lib/sqfs/data_writer/internal.h index 9072c19..1aa600b 100644 --- a/lib/sqfs/data_writer/internal.h +++ b/lib/sqfs/data_writer/internal.h @@ -103,9 +103,9 @@ struct sqfs_data_writer_t { /* file API */ sqfs_inode_generic_t *inode; + sqfs_block_t *blk_current; uint32_t blk_flags; size_t blk_index; - bool had_fragment; /* used only by workers */ size_t max_block_size; diff --git a/lib/sqfshelper/data_writer.c b/lib/sqfshelper/data_writer.c index ca47447..71dd4be 100644 --- a/lib/sqfshelper/data_writer.c +++ b/lib/sqfshelper/data_writer.c @@ -9,13 +9,15 @@ #include "highlevel.h" #include "util.h" +static uint8_t buffer[4096]; + int write_data_from_file(sqfs_data_writer_t *data, sqfs_inode_generic_t *inode, sqfs_file_t *file, size_t block_size, int flags) { uint64_t filesz, offset; - sqfs_block_t *blk; size_t diff; int ret; + (void)block_size; (void)flags; if (sqfs_data_writer_begin_file(data, inode, 0)) @@ -24,20 +26,19 @@ int write_data_from_file(sqfs_data_writer_t *data, sqfs_inode_generic_t *inode, sqfs_inode_get_file_size(inode, &filesz); for (offset = 0; offset < filesz; offset += diff) { - if (filesz - offset > (uint64_t)block_size) { - diff = block_size; + if (filesz - offset > sizeof(buffer)) { + diff = sizeof(buffer); } else { diff = filesz - offset; } - ret = sqfs_file_create_block(file, offset, diff, - NULL, 0, &blk); - + ret = file->read_at(file, offset, buffer, diff); if (ret) - return -1; + return ret; - if (sqfs_data_writer_enqueue(data, blk)) - return -1; + ret = sqfs_data_writer_append(data, buffer, diff); + if (ret) + return ret; } return sqfs_data_writer_end_file(data); |