summaryrefslogtreecommitdiff
path: root/lib/sqfs/xattr_reader.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs/xattr_reader.c')
-rw-r--r--lib/sqfs/xattr_reader.c168
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: