summaryrefslogtreecommitdiff
path: root/lib/sqfs/data_writer/fileapi.c
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 /lib/sqfs/data_writer/fileapi.c
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>
Diffstat (limited to 'lib/sqfs/data_writer/fileapi.c')
-rw-r--r--lib/sqfs/data_writer/fileapi.c78
1 files changed, 59 insertions, 19 deletions
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;
}