summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-26 18:55:04 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-26 18:55:04 +0200
commit9ed84dac57944149e05646960a715d8f98dabcc5 (patch)
tree1be14b86b10b96d0549b1839078c0c19c588f77e
parentff4a9235feb4237854ff102c4dc7cf4645d6a116 (diff)
Replace the data writer enqueue with "append buffer to current file"
This commit turns the file interface into an actual, generic file interface and does away with having to move around blocks outside the data writer. Instead the data writer takes over full control and responsibility of dividing the input data up into blocks propperly. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/sqfs/data_writer.h19
-rw-r--r--lib/sqfs/data_writer/common.c1
-rw-r--r--lib/sqfs/data_writer/fileapi.c78
-rw-r--r--lib/sqfs/data_writer/internal.h2
-rw-r--r--lib/sqfshelper/data_writer.c19
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);