diff options
Diffstat (limited to 'mkfs')
| -rw-r--r-- | mkfs/block.c | 183 | ||||
| -rw-r--r-- | mkfs/mkfs.c | 32 | ||||
| -rw-r--r-- | mkfs/mkfs.h | 25 | 
3 files changed, 135 insertions, 105 deletions
| diff --git a/mkfs/block.c b/mkfs/block.c index 896cefc..4bc9684 100644 --- a/mkfs/block.c +++ b/mkfs/block.c @@ -2,22 +2,37 @@  #include "mkfs.h"  #include "util.h" -static int write_compressed(sqfs_info_t *info, const void *in, size_t size, +struct data_writer_t { +	void *block; +	void *fragment; +	void *scratch; + +	sqfs_fragment_t *fragments; +	size_t num_fragments; +	size_t max_fragments; +	size_t frag_offset; + +	sqfs_super_t *super; +	compressor_t *cmp; +	int outfd; +}; + +static int write_compressed(data_writer_t *data, const void *in, size_t size,  			    uint32_t *outsize)  {  	ssize_t ret; -	ret = info->cmp->do_block(info->cmp, in, size, info->scratch, -				  info->super.block_size); +	ret = data->cmp->do_block(data->cmp, in, size, data->scratch, +				  data->super->block_size);  	if (ret < 0)  		return -1;  	if (ret > 0 && (size_t)ret < size) {  		size = ret; -		ret = write_retry(info->outfd, info->scratch, size); +		ret = write_retry(data->outfd, data->scratch, size);  		*outsize = size;  	} else { -		ret = write_retry(info->outfd, in, size); +		ret = write_retry(data->outfd, in, size);  		*outsize = size | (1 << 24);  	} @@ -31,58 +46,58 @@ static int write_compressed(sqfs_info_t *info, const void *in, size_t size,  		return -1;  	} -	info->super.bytes_used += ret; +	data->super->bytes_used += ret;  	return 0;  } -static int grow_fragment_table(sqfs_info_t *info) +static int grow_fragment_table(data_writer_t *data)  {  	size_t newsz;  	void *new; -	if (info->num_fragments == info->max_fragments) { -		newsz = info->max_fragments ? info->max_fragments * 2 : 16; -		new = realloc(info->fragments, -			      sizeof(info->fragments[0]) * newsz); +	if (data->num_fragments == data->max_fragments) { +		newsz = data->max_fragments ? data->max_fragments * 2 : 16; +		new = realloc(data->fragments, +			      sizeof(data->fragments[0]) * newsz);  		if (new == NULL) {  			perror("appending to fragment table");  			return -1;  		} -		info->max_fragments = newsz; -		info->fragments = new; +		data->max_fragments = newsz; +		data->fragments = new;  	}  	return 0;  } -static int flush_fragments(sqfs_info_t *info) +int data_writer_flush_fragments(data_writer_t *data)  {  	uint64_t offset;  	uint32_t out; -	if (grow_fragment_table(info)) +	if (grow_fragment_table(data))  		return -1; -	offset = info->super.bytes_used; +	offset = data->super->bytes_used; -	if (write_compressed(info, info->fragment, info->frag_offset, &out)) +	if (write_compressed(data, data->fragment, data->frag_offset, &out))  		return -1; -	info->fragments[info->num_fragments].start_offset = htole64(offset); -	info->fragments[info->num_fragments].pad0 = 0; -	info->fragments[info->num_fragments].size = htole32(out); +	data->fragments[data->num_fragments].start_offset = htole64(offset); +	data->fragments[data->num_fragments].pad0 = 0; +	data->fragments[data->num_fragments].size = htole32(out); -	info->num_fragments += 1; -	info->frag_offset = 0; +	data->num_fragments += 1; +	data->frag_offset = 0; -	info->super.flags &= ~SQFS_FLAG_NO_FRAGMENTS; -	info->super.flags |= SQFS_FLAG_ALWAYS_FRAGMENTS; +	data->super->flags &= ~SQFS_FLAG_NO_FRAGMENTS; +	data->super->flags |= SQFS_FLAG_ALWAYS_FRAGMENTS;  	return 0;  } -static int write_data_from_fd(sqfs_info_t *info, file_info_t *fi, int infd) +int write_data_from_fd(data_writer_t *data, file_info_t *fi, int infd)  {  	uint64_t count = fi->size;  	int blk_idx = 0; @@ -90,33 +105,33 @@ static int write_data_from_fd(sqfs_info_t *info, file_info_t *fi, int infd)  	ssize_t ret;  	size_t diff; -	fi->startblock = info->super.bytes_used; +	fi->startblock = data->super->bytes_used;  	while (count != 0) { -		diff = count > (uint64_t)info->super.block_size ? -			info->super.block_size : count; +		diff = count > (uint64_t)data->super->block_size ? +			data->super->block_size : count; -		ret = read_retry(infd, info->block, diff); +		ret = read_retry(infd, data->block, diff);  		if (ret < 0)  			goto fail_read;  		if ((size_t)ret < diff)  			goto fail_trunc; -		if (diff < info->super.block_size) { -			if (info->frag_offset + diff > info->super.block_size) { -				if (flush_fragments(info)) +		if (diff < data->super->block_size) { +			if (data->frag_offset + diff > data->super->block_size) { +				if (data_writer_flush_fragments(data))  					return -1;  			} -			fi->fragment_offset = info->frag_offset; -			fi->fragment = info->num_fragments; +			fi->fragment_offset = data->frag_offset; +			fi->fragment = data->num_fragments; -			memcpy((char *)info->fragment + info->frag_offset, -			       info->block, diff); -			info->frag_offset += diff; +			memcpy((char *)data->fragment + data->frag_offset, +			       data->block, diff); +			data->frag_offset += diff;  		} else { -			if (write_compressed(info, info->block, -					     info->super.block_size, &out)) { +			if (write_compressed(data, data->block, +					     data->super->block_size, &out)) {  				return -1;  			} @@ -135,7 +150,50 @@ fail_trunc:  	return -1;  } -static int process_file(sqfs_info_t *info, file_info_t *fi) +data_writer_t *data_writer_create(sqfs_super_t *super, compressor_t *cmp, +				  int outfd) +{ +	data_writer_t *data; + +	data = calloc(1, sizeof(*data) + super->block_size * 3); +	if (data == NULL) { +		perror("creating data writer"); +		return NULL; +	} + +	data->block = (char *)data + sizeof(*data); +	data->fragment = (char *)data->block + super->block_size; +	data->scratch = (char *)data->fragment + super->block_size; + +	data->super = super; +	data->cmp = cmp; +	data->outfd = outfd; +	return data; +} + +void data_writer_destroy(data_writer_t *data) +{ +	free(data->fragments); +	free(data); +} + +int data_writer_write_fragment_table(data_writer_t *data) +{ +	uint64_t start; + +	data->super->fragment_entry_count = data->num_fragments; + +	if (sqfs_write_table(data->outfd, data->super, data->fragments, +			     sizeof(data->fragments[0]), data->num_fragments, +			     &start, data->cmp)) { +		return -1; +	} + +	data->super->fragment_table_start = start; +	return 0; +} + +static int process_file(data_writer_t *data, file_info_t *fi)  {  	int ret, infd; @@ -145,7 +203,7 @@ static int process_file(sqfs_info_t *info, file_info_t *fi)  		return -1;  	} -	ret = write_data_from_fd(info, fi, infd); +	ret = write_data_from_fd(data, fi, infd);  	close(infd);  	return ret; @@ -161,12 +219,12 @@ static void print_name(tree_node_t *n)  	fputs(n->name, stdout);  } -static int find_and_process_files(sqfs_info_t *info, tree_node_t *n, +static int find_and_process_files(data_writer_t *data, tree_node_t *n,  				  bool quiet)  {  	if (S_ISDIR(n->mode)) {  		for (n = n->data.dir->children; n != NULL; n = n->next) { -			if (find_and_process_files(info, n, quiet)) +			if (find_and_process_files(data, n, quiet))  				return -1;  		}  		return 0; @@ -179,13 +237,13 @@ static int find_and_process_files(sqfs_info_t *info, tree_node_t *n,  			fputc('\n', stdout);  		} -		return process_file(info, n->data.file); +		return process_file(data, n->data.file);  	}  	return 0;  } -int write_data_to_image(sqfs_info_t *info) +int write_data_to_image(data_writer_t *data, sqfs_info_t *info)  {  	bool need_restore = false;  	const char *ptr; @@ -206,40 +264,9 @@ int write_data_to_image(sqfs_info_t *info)  		}  	} -	info->block = malloc(info->super.block_size); - -	if (info->block == NULL) { -		perror("allocating data block buffer"); -		return -1; -	} - -	info->fragment = malloc(info->super.block_size); - -	if (info->fragment == NULL) { -		perror("allocating fragment buffer"); -		free(info->block); -		return -1; -	} - -	info->scratch = malloc(info->super.block_size); -	if (info->scratch == NULL) { -		perror("allocating scratch buffer"); -		free(info->block); -		free(info->fragment); -		return -1; -	} - -	ret = find_and_process_files(info, info->fs.root, info->opt.quiet); - -	ret = ret == 0 ? flush_fragments(info) : ret; - -	free(info->block); -	free(info->fragment); -	free(info->scratch); +	ret = find_and_process_files(data, info->fs.root, info->opt.quiet); -	info->block = NULL; -	info->fragment = NULL; -	info->scratch = NULL; +	ret = ret == 0 ? data_writer_flush_fragments(data) : ret;  	if (need_restore)  		ret = popd(); diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c index 019a233..77e9581 100644 --- a/mkfs/mkfs.c +++ b/mkfs/mkfs.c @@ -40,8 +40,8 @@ static int padd_file(sqfs_info_t *info)  int main(int argc, char **argv)  {  	int status = EXIT_FAILURE, ret; +	data_writer_t *data;  	sqfs_info_t info; -	uint64_t start;  	memset(&info, 0, sizeof(info)); @@ -111,39 +111,37 @@ int main(int argc, char **argv)  		info.super.bytes_used += ret;  	} -	if (write_data_to_image(&info)) +	data = data_writer_create(&info.super, info.cmp, info.outfd); +	if (data == NULL)  		goto out_cmp; +	if (write_data_to_image(data, &info)) +		goto out_data; +  	if (sqfs_serialize_fstree(info.outfd, &info.super, &info.fs,  				  info.cmp, &info.idtbl)) { -		goto out_cmp; -	} - -	info.super.fragment_entry_count = info.num_fragments; - -	if (sqfs_write_table(info.outfd, &info.super, info.fragments, -			     sizeof(info.fragments[0]), info.num_fragments, -			     &start, info.cmp)) { -		goto out_cmp; +		goto out_data;  	} -	info.super.fragment_table_start = start; +	if (data_writer_write_fragment_table(data)) +		goto out_data;  	if (id_table_write(&info.idtbl, info.outfd, &info.super, info.cmp)) -		goto out_cmp; +		goto out_data;  	if (write_xattr(&info)) -		goto out_cmp; +		goto out_data;  	if (sqfs_super_write(&info.super, info.outfd)) -		goto out_cmp; +		goto out_data;  	if (padd_file(&info)) -		goto out_cmp; +		goto out_data;  	status = EXIT_SUCCESS; +out_data: +	data_writer_destroy(data);  out_cmp: -	free(info.fragments);  	info.cmp->destroy(info.cmp);  out_fstree:  	fstree_cleanup(&info.fs); diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h index fe4123b..63bfc10 100644 --- a/mkfs/mkfs.h +++ b/mkfs/mkfs.h @@ -35,19 +35,13 @@ typedef struct {  	char *comp_extra;  } options_t; +typedef struct data_writer_t data_writer_t; +  typedef struct {  	int outfd;  	options_t opt;  	sqfs_super_t super;  	fstree_t fs; -	void *block; -	void *fragment; -	void *scratch; - -	sqfs_fragment_t *fragments; -	size_t num_fragments; -	size_t max_fragments; -	size_t frag_offset;  	id_table_t idtbl; @@ -56,8 +50,19 @@ typedef struct {  void process_command_line(options_t *opt, int argc, char **argv); -int write_data_to_image(sqfs_info_t *info); -  int write_xattr(sqfs_info_t *info); +data_writer_t *data_writer_create(sqfs_super_t *super, compressor_t *cmp, +				  int outfd); + +void data_writer_destroy(data_writer_t *data); + +int data_writer_write_fragment_table(data_writer_t *data); + +int write_data_from_fd(data_writer_t *data, file_info_t *fi, int infd); + +int data_writer_flush_fragments(data_writer_t *data); + +int write_data_to_image(data_writer_t *data, sqfs_info_t *info); +  #endif /* MKFS_H */ | 
