diff options
Diffstat (limited to 'lib/sqfs/xattr_reader.c')
-rw-r--r-- | lib/sqfs/xattr_reader.c | 168 |
1 files changed, 80 insertions, 88 deletions
diff --git a/lib/sqfs/xattr_reader.c b/lib/sqfs/xattr_reader.c index aeee574..80731ba 100644 --- a/lib/sqfs/xattr_reader.c +++ b/lib/sqfs/xattr_reader.c @@ -10,12 +10,12 @@ #include "sqfs/meta_reader.h" #include "sqfs/super.h" #include "sqfs/xattr.h" +#include "sqfs/error.h" #include "sqfs/data.h" #include "util.h" #include <stdlib.h> #include <string.h> -#include <stdio.h> #include <errno.h> struct sqfs_xattr_reader_t { @@ -29,24 +29,28 @@ struct sqfs_xattr_reader_t { sqfs_meta_reader_t *idrd; sqfs_meta_reader_t *kvrd; sqfs_super_t *super; + int sqfsfd; }; -static int get_id_block_locations(sqfs_xattr_reader_t *xr, int sqfsfd, - sqfs_super_t *super) +int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr) { sqfs_xattr_id_table_t idtbl; size_t i; + int err; - if (super->xattr_id_table_start >= super->bytes_used) { - fputs("xattr ID location table is after end of filesystem\n", - stderr); - return -1; - } + if (xr->super->flags & SQFS_FLAG_NO_XATTRS) + return 0; + + if (xr->super->xattr_id_table_start == 0xFFFFFFFFFFFFFFFF) + return 0; + + if (xr->super->xattr_id_table_start >= xr->super->bytes_used) + return SQFS_ERROR_OUT_OF_BOUNDS; if (read_data_at("reading xattr ID location table", - super->xattr_id_table_start, - sqfsfd, &idtbl, sizeof(idtbl))) { - return -1; + xr->super->xattr_id_table_start, + xr->sqfsfd, &idtbl, sizeof(idtbl))) { + return SQFS_ERROR_IO; } xr->xattr_start = le64toh(idtbl.xattr_table_start); @@ -59,23 +63,24 @@ static int get_id_block_locations(sqfs_xattr_reader_t *xr, int sqfsfd, 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 (errno == EOVERFLOW) + return SQFS_ERROR_OVERFLOW; + return SQFS_ERROR_ALLOC; } if (read_data_at("reading xattr ID block locations", - super->xattr_id_table_start + sizeof(idtbl), - sqfsfd, xr->id_block_starts, + xr->super->xattr_id_table_start + sizeof(idtbl), + xr->sqfsfd, xr->id_block_starts, sizeof(uint64_t) * xr->num_id_blocks)) { + err = SQFS_ERROR_IO; 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); + if (xr->id_block_starts[i] > xr->super->bytes_used) { + err = SQFS_ERROR_OUT_OF_BOUNDS; goto fail; } } @@ -84,119 +89,113 @@ static int get_id_block_locations(sqfs_xattr_reader_t *xr, int sqfsfd, fail: free(xr->id_block_starts); xr->id_block_starts = NULL; - return -1; + return err; } -sqfs_xattr_entry_t *sqfs_xattr_reader_read_key(sqfs_xattr_reader_t *xr) +int sqfs_xattr_reader_read_key(sqfs_xattr_reader_t *xr, + sqfs_xattr_entry_t **key_out) { sqfs_xattr_entry_t key, *out; const char *prefix; size_t plen, total; + int ret; - if (sqfs_meta_reader_read(xr->kvrd, &key, sizeof(key))) - return NULL; + ret = sqfs_meta_reader_read(xr->kvrd, &key, sizeof(key)); + if (ret) + return ret; key.type = le16toh(key.type); key.size = le16toh(key.size); prefix = sqfs_get_xattr_prefix(key.type & SQFS_XATTR_PREFIX_MASK); - if (prefix == NULL) { - fprintf(stderr, "found unknown xattr type %u\n", - key.type & SQFS_XATTR_PREFIX_MASK); - return NULL; - } + if (prefix == NULL) + return SQFS_ERROR_UNSUPPORTED; 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; + return SQFS_ERROR_OVERFLOW; } out = calloc(1, total); - if (out == NULL) { - goto fail_alloc; - } + if (out == NULL) + return SQFS_ERROR_ALLOC; *out = key; memcpy(out->key, prefix, plen); - if (sqfs_meta_reader_read(xr->kvrd, out->key + plen, key.size)) { + ret = sqfs_meta_reader_read(xr->kvrd, out->key + plen, key.size); + if (ret) { free(out); - return NULL; + return ret; } - return out; -fail_alloc: - perror("allocating xattr key"); - return NULL; + *key_out = out; + return 0; } -sqfs_xattr_value_t *sqfs_xattr_reader_read_value(sqfs_xattr_reader_t *xr, - const sqfs_xattr_entry_t *key) +int sqfs_xattr_reader_read_value(sqfs_xattr_reader_t *xr, + const sqfs_xattr_entry_t *key, + sqfs_xattr_value_t **val_out) { size_t offset, new_offset, size; sqfs_xattr_value_t value, *out; uint64_t ref, start, new_start; + int ret; - if (sqfs_meta_reader_read(xr->kvrd, &value, sizeof(value))) - return NULL; + ret = sqfs_meta_reader_read(xr->kvrd, &value, sizeof(value)); + if (ret) + return ret; if (key->type & SQFS_XATTR_FLAG_OOL) { - if (sqfs_meta_reader_read(xr->kvrd, &ref, sizeof(ref))) - return NULL; + ret = sqfs_meta_reader_read(xr->kvrd, &ref, sizeof(ref)); + if (ret) + return ret; sqfs_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_start >= xr->super->bytes_used) + return SQFS_ERROR_OUT_OF_BOUNDS; - if (new_offset >= SQFS_META_BLOCK_SIZE) { - fputs("OOL xattr reference points outside " - "metadata block\n", stderr); - return NULL; - } + new_offset = ref & 0xFFFF; + if (new_offset >= SQFS_META_BLOCK_SIZE) + return SQFS_ERROR_OUT_OF_BOUNDS; - if (sqfs_meta_reader_seek(xr->kvrd, new_start, new_offset)) - return NULL; + ret = sqfs_meta_reader_seek(xr->kvrd, new_start, new_offset); + if (ret) + return ret; } 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; + return SQFS_ERROR_OVERFLOW; } out = calloc(1, size); if (out == NULL) - goto fail_alloc; + return SQFS_ERROR_ALLOC; *out = value; - if (sqfs_meta_reader_read(xr->kvrd, out->value, value.size)) + ret = sqfs_meta_reader_read(xr->kvrd, out->value, value.size); + if (ret) goto fail; if (key->type & SQFS_XATTR_FLAG_OOL) { - if (sqfs_meta_reader_seek(xr->kvrd, start, offset)) + ret = sqfs_meta_reader_seek(xr->kvrd, start, offset); + if (ret) goto fail; } - return out; -fail_alloc: - perror("allocating xattr value"); - return NULL; + *val_out = out; + return 0; fail: free(out); - return NULL; + return ret; } int sqfs_xattr_reader_seek_kv(sqfs_xattr_reader_t *xr, @@ -212,38 +211,35 @@ int sqfs_xattr_reader_get_desc(sqfs_xattr_reader_t *xr, uint32_t idx, sqfs_xattr_id_t *desc) { size_t block, offset; + int ret; memset(desc, 0, sizeof(*desc)); if (idx == 0xFFFFFFFF) return 0; - if (xr->kvrd == NULL || xr->idrd == NULL) { - if (idx != 0) - goto fail_bounds; - return 0; - } + if (xr->kvrd == NULL || xr->idrd == NULL) + return idx == 0 ? 0 : SQFS_ERROR_OUT_OF_BOUNDS; if (idx >= xr->num_ids) - goto fail_bounds; + return SQFS_ERROR_OUT_OF_BOUNDS; offset = (idx * sizeof(*desc)) % SQFS_META_BLOCK_SIZE; block = (idx * sizeof(*desc)) / SQFS_META_BLOCK_SIZE; - if (sqfs_meta_reader_seek(xr->idrd, xr->id_block_starts[block], offset)) - return -1; + ret = sqfs_meta_reader_seek(xr->idrd, xr->id_block_starts[block], + offset); + if (ret) + return ret; - if (sqfs_meta_reader_read(xr->idrd, desc, sizeof(*desc))) - return -1; + ret = sqfs_meta_reader_read(xr->idrd, desc, sizeof(*desc)); + if (ret) + return ret; desc->xattr = le64toh(desc->xattr); desc->count = le32toh(desc->count); desc->size = le32toh(desc->size); return 0; -fail_bounds: - fprintf(stderr, "Tried to access out of bounds " - "xattr index: 0x%08X\n", idx); - return -1; } void sqfs_xattr_reader_destroy(sqfs_xattr_reader_t *xr) @@ -263,10 +259,8 @@ sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, sqfs_super_t *super, { sqfs_xattr_reader_t *xr = calloc(1, sizeof(*xr)); - if (xr == NULL) { - perror("creating xattr reader"); + if (xr == NULL) return NULL; - } if (super->flags & SQFS_FLAG_NO_XATTRS) return xr; @@ -274,9 +268,6 @@ sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, sqfs_super_t *super, if (super->xattr_id_table_start == 0xFFFFFFFFFFFFFFFF) return xr; - if (get_id_block_locations(xr, sqfsfd, super)) - goto fail; - xr->idrd = sqfs_meta_reader_create(sqfsfd, cmp, super->id_table_start, super->bytes_used); @@ -289,6 +280,7 @@ sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, sqfs_super_t *super, if (xr->kvrd == NULL) goto fail; + xr->sqfsfd = sqfsfd; xr->super = super; return xr; fail: |