diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-09-26 17:21:44 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-09-26 17:22:53 +0200 | 
| commit | ff4a9235feb4237854ff102c4dc7cf4645d6a116 (patch) | |
| tree | 18017f7f1b6776ef76360fef0ff127d42f3007cd /lib | |
| parent | 248765bd9f6ead4fbe4e5822bcaf46b85fe1687f (diff) | |
Add file API stub to sqfs data writer
Basically move the state tracking from the old data writer over to
the new one.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sqfs/Makemodule.am | 1 | ||||
| -rw-r--r-- | lib/sqfs/data_writer/fileapi.c | 101 | ||||
| -rw-r--r-- | lib/sqfs/data_writer/internal.h | 12 | ||||
| -rw-r--r-- | lib/sqfs/data_writer/pthread.c | 31 | ||||
| -rw-r--r-- | lib/sqfs/data_writer/serial.c | 16 | ||||
| -rw-r--r-- | lib/sqfshelper/data_writer.c | 87 | 
6 files changed, 145 insertions, 103 deletions
| diff --git a/lib/sqfs/Makemodule.am b/lib/sqfs/Makemodule.am index 36a8cc8..a474423 100644 --- a/lib/sqfs/Makemodule.am +++ b/lib/sqfs/Makemodule.am @@ -21,6 +21,7 @@ libsquashfs_la_SOURCES += lib/sqfs/inode.c lib/sqfs/data_writer/fragment.c  libsquashfs_la_SOURCES += lib/sqfs/data_writer/block.c lib/sqfs/io.c  libsquashfs_la_SOURCES += lib/sqfs/data_writer/internal.h lib/sqfs/data_reader.c  libsquashfs_la_SOURCES += lib/sqfs/data_writer/common.c +libsquashfs_la_SOURCES += lib/sqfs/data_writer/fileapi.c  libsquashfs_la_CPPFLAGS = $(AM_CPPFLAGS)  libsquashfs_la_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS)  libsquashfs_la_CFLAGS += $(XZ_CFLAGS) $(LZO_CFLAGS) $(LZ4_CFLAGS) diff --git a/lib/sqfs/data_writer/fileapi.c b/lib/sqfs/data_writer/fileapi.c new file mode 100644 index 0000000..b78d012 --- /dev/null +++ b/lib/sqfs/data_writer/fileapi.c @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * fileapi.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#define SQFS_BUILDING_DLL +#include "internal.h" + +static bool is_zero_block(unsigned char *ptr, size_t size) +{ +	return ptr[0] == 0 && memcmp(ptr, ptr + 1, size - 1) == 0; +} + +static int add_sentinel_block(sqfs_data_writer_t *proc) +{ +	sqfs_block_t *blk = calloc(1, sizeof(*blk)); + +	if (blk == NULL) +		return test_and_set_status(proc, SQFS_ERROR_ALLOC); + +	blk->inode = proc->inode; +	blk->flags = proc->blk_flags | SQFS_BLK_LAST_BLOCK; + +	return data_writer_enqueue(proc, blk); +} + +int sqfs_data_writer_begin_file(sqfs_data_writer_t *proc, +				sqfs_inode_generic_t *inode, uint32_t flags) +{ +	if (proc->inode != NULL) +		return test_and_set_status(proc, SQFS_ERROR_INTERNAL); + +	if (flags & ~SQFS_BLK_USER_SETTABLE_FLAGS) +		return test_and_set_status(proc, SQFS_ERROR_UNSUPPORTED); + +	proc->inode = inode; +	proc->blk_flags = flags; +	proc->blk_index = 0; +	proc->had_fragment = false; +	return 0; +} + +int sqfs_data_writer_enqueue(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; + +	if (is_zero_block(block->data, block->size)) { +		sqfs_inode_make_extended(proc->inode); +		proc->inode->data.file_ext.sparse += block->size; +		proc->inode->num_file_blocks += 1; +		proc->inode->block_sizes[block->index] = 0; +		free(block); +		return 0; +	} + +	if (block->size < proc->max_block_size) { +		if (block->index > 0) { +			err = add_sentinel_block(proc); + +			if (err) { +				free(block); +				return err; +			} +		} + +		proc->had_fragment = true; +		block->flags |= SQFS_BLK_IS_FRAGMENT; +	} else { +		if (block->index == 0) +			block->flags |= SQFS_BLK_FIRST_BLOCK; + +		proc->inode->num_file_blocks += 1; +	} + +	return data_writer_enqueue(proc, block); +} + +int sqfs_data_writer_end_file(sqfs_data_writer_t *proc) +{ +	int err; + +	if (proc->inode == NULL) +		return test_and_set_status(proc, SQFS_ERROR_INTERNAL); + +	if (!proc->had_fragment && proc->inode->num_file_blocks > 0) { +		err = add_sentinel_block(proc); +		if (err) +			return err; +	} + +	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 53ddc5f..9072c19 100644 --- a/lib/sqfs/data_writer/internal.h +++ b/lib/sqfs/data_writer/internal.h @@ -101,6 +101,12 @@ struct sqfs_data_writer_t {  	const sqfs_block_hooks_t *hooks;  	void *user_ptr; +	/* file API */ +	sqfs_inode_generic_t *inode; +	uint32_t blk_flags; +	size_t blk_index; +	bool had_fragment; +  	/* used only by workers */  	size_t max_block_size; @@ -138,4 +144,10 @@ SQFS_INTERNAL  int data_writer_do_block(sqfs_block_t *block, sqfs_compressor_t *cmp,  			 uint8_t *scratch, size_t scratch_size); +SQFS_INTERNAL +int test_and_set_status(sqfs_data_writer_t *proc, int status); + +SQFS_INTERNAL +int data_writer_enqueue(sqfs_data_writer_t *proc, sqfs_block_t *block); +  #endif /* INTERNAL_H */ diff --git a/lib/sqfs/data_writer/pthread.c b/lib/sqfs/data_writer/pthread.c index 3170c11..9c9b0a2 100644 --- a/lib/sqfs/data_writer/pthread.c +++ b/lib/sqfs/data_writer/pthread.c @@ -156,18 +156,6 @@ static void append_to_work_queue(sqfs_data_writer_t *proc,  	pthread_cond_broadcast(&proc->queue_cond);  } -static int test_and_set_status(sqfs_data_writer_t *proc, int status) -{ -	pthread_mutex_lock(&proc->mtx); -	if (proc->status == 0) { -		proc->status = status; -	} else { -		status = proc->status; -	} -	pthread_cond_broadcast(&proc->queue_cond); -	return status; -} -  static sqfs_block_t *try_dequeue(sqfs_data_writer_t *proc)  {  	sqfs_block_t *queue, *it, *prev; @@ -260,16 +248,23 @@ static int process_done_queue(sqfs_data_writer_t *proc, sqfs_block_t *queue)  	return status;  } -int sqfs_data_writer_enqueue(sqfs_data_writer_t *proc, sqfs_block_t *block) +int test_and_set_status(sqfs_data_writer_t *proc, int status) +{ +	pthread_mutex_lock(&proc->mtx); +	if (proc->status == 0) { +		proc->status = status; +	} else { +		status = proc->status; +	} +	pthread_cond_broadcast(&proc->queue_cond); +	return status; +} + +int data_writer_enqueue(sqfs_data_writer_t *proc, sqfs_block_t *block)  {  	sqfs_block_t *queue;  	int status; -	if (block->flags & ~SQFS_BLK_USER_SETTABLE_FLAGS) { -		free(block); -		return test_and_set_status(proc, SQFS_ERROR_UNSUPPORTED); -	} -  	pthread_mutex_lock(&proc->mtx);  	while (proc->backlog > proc->max_backlog && proc->status == 0)  		pthread_cond_wait(&proc->done_cond, &proc->mtx); diff --git a/lib/sqfs/data_writer/serial.c b/lib/sqfs/data_writer/serial.c index 38dcc58..916f497 100644 --- a/lib/sqfs/data_writer/serial.c +++ b/lib/sqfs/data_writer/serial.c @@ -35,7 +35,15 @@ void sqfs_data_writer_destroy(sqfs_data_writer_t *proc)  	data_writer_cleanup(proc);  } -int sqfs_data_writer_enqueue(sqfs_data_writer_t *proc, sqfs_block_t *block) +int test_and_set_status(sqfs_data_writer_t *proc, int status) +{ +	if (proc->status == 0) +		proc->status = status; + +	return proc->status; +} + +int data_writer_enqueue(sqfs_data_writer_t *proc, sqfs_block_t *block)  {  	sqfs_block_t *fragblk = NULL; @@ -44,12 +52,6 @@ int sqfs_data_writer_enqueue(sqfs_data_writer_t *proc, sqfs_block_t *block)  		return proc->status;  	} -	if (block->flags & ~SQFS_BLK_USER_SETTABLE_FLAGS) { -		proc->status = SQFS_ERROR_UNSUPPORTED; -		free(block); -		return proc->status; -	} -  	if (block->flags & SQFS_BLK_IS_FRAGMENT) {  		block->checksum = crc32(0, block->data, block->size); diff --git a/lib/sqfshelper/data_writer.c b/lib/sqfshelper/data_writer.c index 5c01cb8..ca47447 100644 --- a/lib/sqfshelper/data_writer.c +++ b/lib/sqfshelper/data_writer.c @@ -9,47 +9,17 @@  #include "highlevel.h"  #include "util.h" -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> - -static bool is_zero_block(unsigned char *ptr, size_t size) -{ -	return ptr[0] == 0 && memcmp(ptr, ptr + 1, size - 1) == 0; -} - -static int add_sentinel_block(sqfs_data_writer_t *data, -			      sqfs_inode_generic_t *inode, -			      uint32_t flags) -{ -	sqfs_block_t *blk = calloc(1, sizeof(*blk)); - -	if (blk == NULL) { -		perror("creating sentinel block"); -		return -1; -	} - -	blk->inode = inode; -	blk->flags = flags; - -	return sqfs_data_writer_enqueue(data, blk); -} -  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)  { -	uint32_t blk_flags = SQFS_BLK_FIRST_BLOCK;  	uint64_t filesz, offset; -	size_t diff, i = 0;  	sqfs_block_t *blk; +	size_t diff;  	int ret; +	(void)flags; -	if (flags & DW_DONT_COMPRESS) -		blk_flags |= SQFS_BLK_DONT_COMPRESS; - -	if (flags & DW_ALLIGN_DEVBLK) -		blk_flags |= SQFS_BLK_ALLIGN; +	if (sqfs_data_writer_begin_file(data, inode, 0)) +		return -1;  	sqfs_inode_get_file_size(inode, &filesz); @@ -60,54 +30,15 @@ int write_data_from_file(sqfs_data_writer_t *data, sqfs_inode_generic_t *inode,  			diff = filesz - offset;  		} -		ret = sqfs_file_create_block(file, offset, diff, inode, -					     blk_flags, &blk); +		ret = sqfs_file_create_block(file, offset, diff, +					     NULL, 0, &blk);  		if (ret)  			return -1; -		blk->index = i++; - -		if (is_zero_block(blk->data, blk->size)) { -			sqfs_inode_make_extended(inode); -			inode->data.file_ext.sparse += blk->size; -			inode->num_file_blocks += 1; - -			inode->block_sizes[blk->index] = 0; -			free(blk); -			continue; -		} - -		if (diff < block_size && !(flags & DW_DONT_FRAGMENT)) { -			if (!(blk_flags & (SQFS_BLK_FIRST_BLOCK | -					   SQFS_BLK_LAST_BLOCK))) { -				blk_flags |= SQFS_BLK_LAST_BLOCK; - -				if (add_sentinel_block(data, inode, -						       blk_flags)) { -					free(blk); -					return -1; -				} -			} - -			blk->flags |= SQFS_BLK_IS_FRAGMENT; - -			if (sqfs_data_writer_enqueue(data, blk)) -				return -1; -		} else { -			if (sqfs_data_writer_enqueue(data, blk)) -				return -1; - -			blk_flags &= ~SQFS_BLK_FIRST_BLOCK; -			inode->num_file_blocks += 1; -		} -	} - -	if (!(blk_flags & (SQFS_BLK_FIRST_BLOCK | SQFS_BLK_LAST_BLOCK))) { -		blk_flags |= SQFS_BLK_LAST_BLOCK; - -		if (add_sentinel_block(data, inode, blk_flags)) +		if (sqfs_data_writer_enqueue(data, blk))  			return -1;  	} -	return 0; + +	return sqfs_data_writer_end_file(data);  } | 
