diff options
Diffstat (limited to 'lib/sqfs')
| -rw-r--r-- | lib/sqfs/frag_reader.c | 81 | ||||
| -rw-r--r-- | lib/sqfs/id_table_read.c | 52 | ||||
| -rw-r--r-- | lib/sqfs/read_table.c | 79 | 
3 files changed, 100 insertions, 112 deletions
| diff --git a/lib/sqfs/frag_reader.c b/lib/sqfs/frag_reader.c index 51b40e9..2adfe01 100644 --- a/lib/sqfs/frag_reader.c +++ b/lib/sqfs/frag_reader.c @@ -1,11 +1,10 @@  /* SPDX-License-Identifier: GPL-3.0-or-later */  #include "config.h" -#include "meta_reader.h"  #include "frag_reader.h" +#include "highlevel.h"  #include "util.h" -#include <unistd.h>  #include <string.h>  #include <stdlib.h>  #include <stdio.h> @@ -66,83 +65,35 @@ static int precache_block(frag_reader_t *f, size_t i)  frag_reader_t *frag_reader_create(sqfs_super_t *super, int fd,  				  compressor_t *cmp)  { -	size_t i, blockcount, j, diff, count;  	sqfs_fragment_t *tbl = NULL; -	uint64_t *locations = NULL; -	meta_reader_t *m = NULL;  	frag_reader_t *f = NULL; +	size_t i; -	count = super->fragment_entry_count; -	blockcount = count / (SQFS_META_BLOCK_SIZE / sizeof(tbl[0])); - -	if (count % (SQFS_META_BLOCK_SIZE / sizeof(tbl[0]))) -		++blockcount; - -	/* pre allocate all the stuff */  	f = calloc(1, sizeof(*f) + super->block_size * 2); -	if (f == NULL) -		goto fail_rd; - -	tbl = calloc(count, sizeof(tbl[0])); -	if (tbl == NULL) -		goto fail_rd; - -	locations = malloc(blockcount * sizeof(locations[0])); -	if (locations == NULL) -		goto fail_rd; - -	/* read the meta block offset table */ -	if (read_data_at("reading fragment table", super->fragment_table_start, -			 fd, locations, blockcount * sizeof(locations[0]))) { -		goto fail; +	if (f == NULL) { +		perror("creating fragment table"); +		return NULL;  	} -	for (i = 0; i < blockcount; ++i) -		locations[i] = le64toh(locations[i]); - -	/* read the meta blocks */ -	m = meta_reader_create(fd, cmp); -	if (m == NULL) -		goto fail; - -	for (i = 0, j = 0; i < blockcount && j < count; ++i, j += diff) { -		if (meta_reader_seek(m, locations[i], 0)) -			goto fail; - -		diff = SQFS_META_BLOCK_SIZE / sizeof(tbl[0]); -		if (diff > (count - j)) -			diff = count - j; +	f->block_size = super->block_size; +	f->num_fragments = super->fragment_entry_count; +	f->current_index = f->num_fragments; +	f->cmp = cmp; +	f->fd = fd; -		if (meta_reader_read(m, tbl + j, diff * sizeof(tbl[0]))) -			goto fail; +	f->tbl = sqfs_read_table(fd, cmp, sizeof(tbl[0]) * f->num_fragments, +				 super->fragment_table_start); +	if (f->tbl == NULL) { +		free(f); +		return NULL;  	} -	for (i = 0; i < count; ++i) { +	for (i = 0; i < f->num_fragments; ++i) {  		tbl[i].start_offset = le64toh(tbl[i].start_offset);  		tbl[i].size = le32toh(tbl[i].size);  	} -	/* cleanup and ship it */ -	meta_reader_destroy(m); -	free(locations); - -	f->tbl = tbl; -	f->num_fragments = count; -	f->cmp = cmp; -	f->fd = fd; -	f->block_size = super->block_size; -	f->current_index = count;  	return f; -fail_rd: -	perror("reading fragment table"); -	goto fail; -fail: -	if (m != NULL) -		meta_reader_destroy(m); -	free(tbl); -	free(locations); -	free(f); -	return NULL;  }  void frag_reader_destroy(frag_reader_t *f) diff --git a/lib/sqfs/id_table_read.c b/lib/sqfs/id_table_read.c index 1e92f75..bed0cf4 100644 --- a/lib/sqfs/id_table_read.c +++ b/lib/sqfs/id_table_read.c @@ -1,21 +1,16 @@  /* SPDX-License-Identifier: GPL-3.0-or-later */  #include "config.h" -#include "meta_reader.h"  #include "highlevel.h"  #include "util.h"  #include <stdlib.h> -#include <unistd.h>  #include <stdio.h>  int id_table_read(id_table_t *tbl, int fd, sqfs_super_t *super,  		  compressor_t *cmp)  { -	size_t i, block_count, count, diff; -	uint64_t blocks[32]; -	meta_reader_t *m; -	uint32_t *ptr; +	size_t i;  	if (tbl->ids != NULL) {  		free(tbl->ids); @@ -29,54 +24,17 @@ int id_table_read(id_table_t *tbl, int fd, sqfs_super_t *super,  		return -1;  	} -	tbl->ids = calloc(super->id_count, sizeof(uint32_t)); -	if (tbl->ids == NULL) { -		perror("reading ID table"); -		return -1; -	} -  	tbl->num_ids = super->id_count;  	tbl->max_ids = super->id_count; - -	block_count = super->id_count / 2048; -	if (super->id_count % 2048) -		++block_count; - -	if (read_data_at("reading ID table", super->id_table_start, fd, -			 blocks, sizeof(blocks[0]) * block_count)) { -		return -1; -	} - -	for (i = 0; i < block_count; ++i) -		blocks[i] = le64toh(blocks[i]); - -	m = meta_reader_create(fd, cmp); -	if (m == NULL) +	tbl->ids = sqfs_read_table(fd, cmp, tbl->num_ids * sizeof(uint32_t), +				   super->id_table_start); +	if (tbl->ids == NULL) { +		free(tbl);  		return -1; - -	count = super->id_count; -	ptr = tbl->ids; - -	for (i = 0; i < block_count && count > 0; ++i) { -		diff = count < 2048 ? count : 2048; - -		if (meta_reader_seek(m, blocks[i], 0)) -			goto fail_meta; - -		if (meta_reader_read(m, ptr, diff * sizeof(tbl->ids[0]))) -			goto fail_meta; - -		count -= diff; -		ptr += diff;  	} -	meta_reader_destroy(m); -  	for (i = 0; i < tbl->num_ids; ++i)  		tbl->ids[i] = le32toh(tbl->ids[i]);  	return 0; -fail_meta: -	meta_reader_destroy(m); -	return -1;  } diff --git a/lib/sqfs/read_table.c b/lib/sqfs/read_table.c new file mode 100644 index 0000000..8fc8ebf --- /dev/null +++ b/lib/sqfs/read_table.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "config.h" + +#include "meta_reader.h" +#include "highlevel.h" +#include "util.h" + +#include <endian.h> +#include <stdlib.h> +#include <stdio.h> + +void *sqfs_read_table(int fd, compressor_t *cmp, size_t table_size, +		      uint64_t location) +{ +	size_t diff, block_count, list_size, blk_idx = 0; +	uint64_t start, *locations; +	meta_reader_t *m; +	void *data, *ptr; + +	data = malloc(table_size); +	if (data == NULL) { +		perror("reading table"); +		return NULL; +	} + +	/* restore list from image */ +	block_count = table_size / SQFS_META_BLOCK_SIZE; + +	if ((table_size % SQFS_META_BLOCK_SIZE) != 0) +		++block_count; + +	list_size = sizeof(uint64_t) * block_count; +	locations = malloc(list_size); + +	if (locations == NULL) { +		perror("allocation table location list"); +		goto fail_data; +	} + +	if (read_data_at("reading table locations", location, +			 fd, locations, list_size)) { +		goto fail_idx; +	} + +	/* Read the actual data */ +	m = meta_reader_create(fd, cmp); +	if (m == NULL) +		goto fail_idx; + +	ptr = data; + +	while (table_size > 0) { +		start = le64toh(locations[blk_idx++]); + +		if (meta_reader_seek(m, start, 0)) +			goto fail; + +		diff = SQFS_META_BLOCK_SIZE; +		if (diff > table_size) +			diff = table_size; + +		if (meta_reader_read(m, ptr, diff)) +			goto fail; + +		ptr = (char *)ptr + diff; +		table_size -= diff; +	} + +	meta_reader_destroy(m); +	free(locations); +	return data; +fail: +	meta_reader_destroy(m); +fail_idx: +	free(locations); +fail_data: +	free(data); +	return NULL; +} | 
