diff options
Diffstat (limited to 'lib/sqfshelper')
| -rw-r--r-- | lib/sqfshelper/deserialize_fstree.c | 1 | ||||
| -rw-r--r-- | lib/sqfshelper/xattr_reader.c | 299 | 
2 files changed, 10 insertions, 290 deletions
| diff --git a/lib/sqfshelper/deserialize_fstree.c b/lib/sqfshelper/deserialize_fstree.c index c418b16..98c59fb 100644 --- a/lib/sqfshelper/deserialize_fstree.c +++ b/lib/sqfshelper/deserialize_fstree.c @@ -9,7 +9,6 @@  #include "sqfs/meta_reader.h"  #include "sqfs/dir.h" -#include "xattr_reader.h"  #include "highlevel.h"  #include <stdlib.h> diff --git a/lib/sqfshelper/xattr_reader.c b/lib/sqfshelper/xattr_reader.c index c13358d..2cf1114 100644 --- a/lib/sqfshelper/xattr_reader.c +++ b/lib/sqfshelper/xattr_reader.c @@ -6,9 +6,7 @@   */  #include "config.h" -#include "sqfs/meta_reader.h" -#include "sqfs/xattr.h" -#include "xattr_reader.h" +#include "highlevel.h"  #include "util.h"  #include <assert.h> @@ -17,226 +15,6 @@  #include <stdio.h>  #include <errno.h> -struct xattr_reader_t { -	uint64_t xattr_start; - -	size_t num_id_blocks; -	size_t num_ids; - -	uint64_t *id_block_starts; - -	meta_reader_t *idrd; -	meta_reader_t *kvrd; -	sqfs_super_t *super; -}; - -static int get_id_block_locations(xattr_reader_t *xr, int sqfsfd, -				  sqfs_super_t *super) -{ -	sqfs_xattr_id_table_t idtbl; -	size_t i; - -	if (super->xattr_id_table_start >= super->bytes_used) { -		fputs("xattr ID location table is after end of filesystem\n", -		      stderr); -		return -1; -	} - -	if (read_data_at("reading xattr ID location table", -			 super->xattr_id_table_start, -			 sqfsfd, &idtbl, sizeof(idtbl))) { -		return -1; -	} - -	xr->xattr_start = le64toh(idtbl.xattr_table_start); -	xr->num_ids = le32toh(idtbl.xattr_ids); -	xr->num_id_blocks = -		(xr->num_ids * sizeof(sqfs_xattr_id_t)) / SQFS_META_BLOCK_SIZE; - -	if ((xr->num_ids * sizeof(sqfs_xattr_id_t)) % SQFS_META_BLOCK_SIZE) -		xr->num_id_blocks += 1; - -	xr->id_block_starts = alloc_array(sizeof(uint64_t), xr->num_id_blocks); -	if (xr->id_block_starts == NULL) { -		perror("allocating xattr ID location table"); -		return -1; -	} - -	if (read_data_at("reading xattr ID block locations", -			 super->xattr_id_table_start + sizeof(idtbl), -			 sqfsfd, xr->id_block_starts, -			 sizeof(uint64_t) * xr->num_id_blocks)) { -		goto fail; -	} - -	for (i = 0; i < xr->num_id_blocks; ++i) { -		xr->id_block_starts[i] = le64toh(xr->id_block_starts[i]); - -		if (xr->id_block_starts[i] > super->bytes_used) { -			fputs("found xattr ID block that is past " -			      "end of filesystem\n", stderr); -			goto fail; -		} -	} - -	return 0; -fail: -	free(xr->id_block_starts); -	xr->id_block_starts = NULL; -	return -1; -} - -static int get_xattr_desc(xattr_reader_t *xr, uint32_t idx, -			  sqfs_xattr_id_t *desc) -{ -	size_t block, offset; - -	if (idx >= xr->num_ids) { -		fprintf(stderr, "Tried to access out of bounds " -			"xattr index: 0x%08X\n", idx); -		return -1; -	} - -	offset = (idx * sizeof(*desc)) % SQFS_META_BLOCK_SIZE; -	block = (idx * sizeof(*desc)) / SQFS_META_BLOCK_SIZE; - -	if (meta_reader_seek(xr->idrd, xr->id_block_starts[block], offset)) -		return -1; - -	if (meta_reader_read(xr->idrd, desc, sizeof(*desc))) -		return -1; - -	desc->xattr = le64toh(desc->xattr); -	desc->count = le32toh(desc->count); -	desc->size = le32toh(desc->size); - -	if ((desc->xattr & 0xFFFF) >= SQFS_META_BLOCK_SIZE) { -		fputs("Found xattr ID record pointing outside " -		      "metadata block\n", stderr); -		return -1; -	} - -	if ((xr->xattr_start + (desc->xattr >> 16)) >= xr->super->bytes_used) { -		fputs("Found xattr ID record pointing past " -		      "end of filesystem\n", stderr); -		return -1; -	} - -	return 0; -} - -static sqfs_xattr_entry_t *read_key(xattr_reader_t *xr) -{ -	sqfs_xattr_entry_t key, *out; -	const char *prefix; -	size_t plen, total; - -	if (meta_reader_read(xr->kvrd, &key, sizeof(key))) -		return NULL; - -	key.type = le16toh(key.type); -	key.size = le16toh(key.size); - -	prefix = sqfs_get_xattr_prefix(key.type & SQUASHFS_XATTR_PREFIX_MASK); -	if (prefix == NULL) { -		fprintf(stderr, "found unknown xattr type %u\n", -			key.type & SQUASHFS_XATTR_PREFIX_MASK); -		return NULL; -	} - -	plen = strlen(prefix); - -	if (SZ_ADD_OV(plen, key.size, &total) || SZ_ADD_OV(total, 1, &total) || -	    SZ_ADD_OV(sizeof(*out), total, &total)) { -		errno = EOVERFLOW; -		goto fail_alloc; -	} - -	out = calloc(1, total); -	if (out == NULL) { -		goto fail_alloc; -	} - -	*out = key; -	memcpy(out->key, prefix, plen); - -	if (meta_reader_read(xr->kvrd, out->key + plen, key.size)) { -		free(out); -		return NULL; -	} - -	return out; -fail_alloc: -	perror("allocating xattr key"); -	return NULL; -} - -static sqfs_xattr_value_t *read_value(xattr_reader_t *xr, -				      const sqfs_xattr_entry_t *key) -{ -	size_t offset, new_offset, size; -	sqfs_xattr_value_t value, *out; -	uint64_t ref, start, new_start; - -	if (meta_reader_read(xr->kvrd, &value, sizeof(value))) -		return NULL; - -	if (key->type & SQUASHFS_XATTR_FLAG_OOL) { -		if (meta_reader_read(xr->kvrd, &ref, sizeof(ref))) -			return NULL; - -		meta_reader_get_position(xr->kvrd, &start, &offset); - -		new_start = xr->xattr_start + (ref >> 16); -		new_offset = ref & 0xFFFF; - -		if (new_start > xr->super->bytes_used) { -			fputs("OOL xattr reference points past end of " -			      "filesystem\n", stderr); -			return NULL; -		} - -		if (new_offset >= SQFS_META_BLOCK_SIZE) { -			fputs("OOL xattr reference points outside " -			      "metadata block\n", stderr); -			return NULL; -		} - -		if (meta_reader_seek(xr->kvrd, new_start, new_offset)) -			return NULL; -	} - -	value.size = le32toh(value.size); - -	if (SZ_ADD_OV(sizeof(*out), value.size, &size) || -	    SZ_ADD_OV(size, 1, &size)) { -		errno = EOVERFLOW; -		goto fail_alloc; -	} - -	out = calloc(1, size); -	if (out == NULL) -		goto fail_alloc; - -	*out = value; - -	if (meta_reader_read(xr->kvrd, out->value, value.size)) -		goto fail; - -	if (key->type & SQUASHFS_XATTR_FLAG_OOL) { -		if (meta_reader_seek(xr->kvrd, start, offset)) -			goto fail; -	} - -	return out; -fail_alloc: -	perror("allocating xattr value"); -	return NULL; -fail: -	free(out); -	return NULL; -} -  static int restore_kv_pairs(xattr_reader_t *xr, fstree_t *fs,  			    tree_node_t *node)  { @@ -245,17 +23,12 @@ static int restore_kv_pairs(xattr_reader_t *xr, fstree_t *fs,  	sqfs_xattr_value_t *val;  	int ret; -	if (meta_reader_seek(xr->kvrd, node->xattr->block, -			     node->xattr->offset)) { -		return -1; -	} -  	for (i = 0; i < node->xattr->num_attr; ++i) { -		key = read_key(xr); +		key = xattr_reader_read_key(xr);  		if (key == NULL)  			return -1; -		val = read_value(xr, key); +		val = xattr_reader_read_value(xr, key);  		if (val == NULL)  			goto fail_key; @@ -302,12 +75,6 @@ int xattr_reader_restore_node(xattr_reader_t *xr, fstree_t *fs,  	sqfs_xattr_id_t desc;  	tree_xattr_t *it; -	if (xr->kvrd == NULL || xr->idrd == NULL) -		return 0; - -	if (xattr == 0xFFFFFFFF) -		return 0; -  	for (it = fs->xattr; it != NULL; it = it->next) {  		if (it->index == xattr) {  			node->xattr = it; @@ -315,9 +82,12 @@ int xattr_reader_restore_node(xattr_reader_t *xr, fstree_t *fs,  		}  	} -	if (get_xattr_desc(xr, xattr, &desc)) +	if (xattr_reader_get_desc(xr, xattr, &desc))  		return -1; +	if (desc.count == 0 || desc.size == 0) +		return 0; +  	node->xattr = alloc_flex(sizeof(*node->xattr),  				 sizeof(node->xattr->attr[0]), desc.count);  	if (node->xattr == NULL) { @@ -327,12 +97,13 @@ int xattr_reader_restore_node(xattr_reader_t *xr, fstree_t *fs,  	node->xattr->num_attr = desc.count;  	node->xattr->max_attr = desc.count; -	node->xattr->block = xr->xattr_start + (desc.xattr >> 16); -	node->xattr->offset = desc.xattr & 0xFFFF;  	node->xattr->size = desc.size;  	node->xattr->index = xattr;  	node->xattr->owner = node; +	if (xattr_reader_seek_kv(xr, &desc)) +		return -1; +  	if (restore_kv_pairs(xr, fs, node)) {  		free(node->xattr);  		return -1; @@ -342,53 +113,3 @@ int xattr_reader_restore_node(xattr_reader_t *xr, fstree_t *fs,  	fs->xattr = node->xattr;  	return 0;  } - -void xattr_reader_destroy(xattr_reader_t *xr) -{ -	if (xr->kvrd != NULL) -		meta_reader_destroy(xr->kvrd); - -	if (xr->idrd != NULL) -		meta_reader_destroy(xr->idrd); - -	free(xr->id_block_starts); -	free(xr); -} - -xattr_reader_t *xattr_reader_create(int sqfsfd, sqfs_super_t *super, -				    compressor_t *cmp) -{ -	xattr_reader_t *xr = calloc(1, sizeof(*xr)); - -	if (xr == NULL) { -		perror("creating xattr reader"); -		return NULL; -	} - -	if (super->flags & SQFS_FLAG_NO_XATTRS) -		return xr; - -	if (super->xattr_id_table_start == 0xFFFFFFFFFFFFFFFF) -		return xr; - -	if (get_id_block_locations(xr, sqfsfd, super)) -		goto fail; - -	xr->idrd = meta_reader_create(sqfsfd, cmp, -				      super->id_table_start, -				      super->bytes_used); -	if (xr->idrd == NULL) -		goto fail; - -	xr->kvrd = meta_reader_create(sqfsfd, cmp, -				      super->id_table_start, -				      super->bytes_used); -	if (xr->kvrd == NULL) -		goto fail; - -	xr->super = super; -	return xr; -fail: -	xattr_reader_destroy(xr); -	return NULL; -} | 
