aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/xattr
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs/xattr')
-rw-r--r--lib/sqfs/xattr/xattr.c49
-rw-r--r--lib/sqfs/xattr/xattr_reader.c336
-rw-r--r--lib/sqfs/xattr/xattr_writer.c127
-rw-r--r--lib/sqfs/xattr/xattr_writer.h63
-rw-r--r--lib/sqfs/xattr/xattr_writer_flush.c347
-rw-r--r--lib/sqfs/xattr/xattr_writer_record.c145
6 files changed, 0 insertions, 1067 deletions
diff --git a/lib/sqfs/xattr/xattr.c b/lib/sqfs/xattr/xattr.c
deleted file mode 100644
index 29ecebf..0000000
--- a/lib/sqfs/xattr/xattr.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * write_xattr.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-#include "sqfs/xattr.h"
-#include "sqfs/error.h"
-
-#include <string.h>
-
-static const struct {
- const char *prefix;
- SQFS_XATTR_TYPE type;
-} xattr_types[] = {
- { "user.", SQFS_XATTR_USER },
- { "trusted.", SQFS_XATTR_TRUSTED },
- { "security.", SQFS_XATTR_SECURITY },
-};
-
-int sqfs_get_xattr_prefix_id(const char *key)
-{
- size_t i, len;
-
- for (i = 0; i < sizeof(xattr_types) / sizeof(xattr_types[0]); ++i) {
- len = strlen(xattr_types[i].prefix);
-
- if (strncmp(key, xattr_types[i].prefix, len) == 0 &&
- strlen(key) > len) {
- return xattr_types[i].type;
- }
- }
-
- return SQFS_ERROR_UNSUPPORTED;
-}
-
-const char *sqfs_get_xattr_prefix(SQFS_XATTR_TYPE id)
-{
- size_t i;
-
- for (i = 0; i < sizeof(xattr_types) / sizeof(xattr_types[0]); ++i) {
- if (xattr_types[i].type == id)
- return xattr_types[i].prefix;
- }
-
- return NULL;
-}
diff --git a/lib/sqfs/xattr/xattr_reader.c b/lib/sqfs/xattr/xattr_reader.c
deleted file mode 100644
index 9e3ea76..0000000
--- a/lib/sqfs/xattr/xattr_reader.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * xattr_reader.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include "sqfs/xattr_reader.h"
-#include "sqfs/meta_reader.h"
-#include "sqfs/super.h"
-#include "sqfs/xattr.h"
-#include "sqfs/error.h"
-#include "sqfs/block.h"
-#include "sqfs/io.h"
-#include "util/util.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-struct sqfs_xattr_reader_t {
- sqfs_object_t base;
-
- sqfs_u64 xattr_start;
- sqfs_u64 xattr_end;
-
- size_t num_id_blocks;
- size_t num_ids;
-
- sqfs_u64 *id_block_starts;
-
- sqfs_meta_reader_t *idrd;
- sqfs_meta_reader_t *kvrd;
-};
-
-static sqfs_object_t *xattr_reader_copy(const sqfs_object_t *obj)
-{
- const sqfs_xattr_reader_t *xr = (const sqfs_xattr_reader_t *)obj;
- sqfs_xattr_reader_t *copy = malloc(sizeof(*copy));
-
- if (copy == NULL)
- return NULL;
-
- memcpy(copy, xr, sizeof(*xr));
-
- if (xr->kvrd != NULL) {
- copy->kvrd = sqfs_copy(xr->kvrd);
- if (copy->kvrd == NULL)
- goto fail;
- }
-
- if (xr->idrd != NULL) {
- copy->idrd = sqfs_copy(xr->idrd);
- if (copy->idrd == NULL)
- goto fail;
- }
-
- if (xr->id_block_starts != NULL) {
- copy->id_block_starts = alloc_array(sizeof(sqfs_u64),
- xr->num_id_blocks);
- if (copy->id_block_starts == NULL)
- goto fail;
-
- memcpy(copy->id_block_starts, xr->id_block_starts,
- sizeof(sqfs_u64) * xr->num_id_blocks);
- }
-
- return (sqfs_object_t *)copy;
-fail:
- sqfs_drop(copy->idrd);
- sqfs_drop(copy->kvrd);
- free(copy);
- return NULL;
-}
-
-static void xattr_reader_destroy(sqfs_object_t *obj)
-{
- sqfs_xattr_reader_t *xr = (sqfs_xattr_reader_t *)obj;
-
- sqfs_drop(xr->kvrd);
- sqfs_drop(xr->idrd);
- free(xr->id_block_starts);
- free(xr);
-}
-
-int sqfs_xattr_reader_load(sqfs_xattr_reader_t *xr, const sqfs_super_t *super,
- sqfs_file_t *file, sqfs_compressor_t *cmp)
-{
- sqfs_xattr_id_table_t idtbl;
- size_t i;
- int err;
-
- /* sanity check */
- if (super->flags & SQFS_FLAG_NO_XATTRS)
- return 0;
-
- if (super->xattr_id_table_start == 0xFFFFFFFFFFFFFFFF)
- return 0;
-
- if (super->xattr_id_table_start >= super->bytes_used)
- return SQFS_ERROR_OUT_OF_BOUNDS;
-
- /* cleanup pre-existing data */
- xr->idrd = sqfs_drop(xr->idrd);
- xr->kvrd = sqfs_drop(xr->kvrd);
-
- free(xr->id_block_starts);
- xr->id_block_starts = NULL;
-
- /* read the locations table */
- err = file->read_at(file, super->xattr_id_table_start,
- &idtbl, sizeof(idtbl));
- if (err)
- return err;
-
- 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(sqfs_u64), xr->num_id_blocks);
- if (xr->id_block_starts == NULL) {
- if (errno == EOVERFLOW)
- return SQFS_ERROR_OVERFLOW;
- return SQFS_ERROR_ALLOC;
- }
-
- err = file->read_at(file, super->xattr_id_table_start + sizeof(idtbl),
- xr->id_block_starts,
- sizeof(sqfs_u64) * xr->num_id_blocks);
- if (err)
- goto fail_blocks;
-
- 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) {
- err = SQFS_ERROR_OUT_OF_BOUNDS;
- goto fail_blocks;
- }
- }
-
- /* create the meta data readers */
- xr->idrd = sqfs_meta_reader_create(file, cmp, super->id_table_start,
- super->bytes_used);
- if (xr->idrd == NULL)
- goto fail_blocks;
-
- xr->kvrd = sqfs_meta_reader_create(file, cmp, super->id_table_start,
- super->bytes_used);
- if (xr->kvrd == NULL)
- goto fail_idrd;
-
- xr->xattr_end = super->bytes_used;
- return 0;
-fail_idrd:
- xr->idrd = sqfs_drop(xr->idrd);
-fail_blocks:
- free(xr->id_block_starts);
- xr->id_block_starts = NULL;
- return err;
-}
-
-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;
-
- 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)
- 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)) {
- return SQFS_ERROR_OVERFLOW;
- }
-
- out = calloc(1, total);
- if (out == NULL)
- return SQFS_ERROR_ALLOC;
-
- *out = key;
- memcpy(out->key, prefix, plen);
-
- ret = sqfs_meta_reader_read(xr->kvrd, out->key + plen, key.size);
- if (ret) {
- free(out);
- return ret;
- }
-
- *key_out = out;
- return 0;
-}
-
-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;
- sqfs_u64 ref, start, new_start;
- int ret;
-
- ret = sqfs_meta_reader_read(xr->kvrd, &value, sizeof(value));
- if (ret)
- return ret;
-
- if (key->type & SQFS_XATTR_FLAG_OOL) {
- 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);
- if (new_start >= xr->xattr_end)
- return SQFS_ERROR_OUT_OF_BOUNDS;
-
- new_offset = ref & 0xFFFF;
- if (new_offset >= SQFS_META_BLOCK_SIZE)
- return SQFS_ERROR_OUT_OF_BOUNDS;
-
- ret = sqfs_meta_reader_seek(xr->kvrd, new_start, new_offset);
- if (ret)
- return ret;
-
- ret = sqfs_meta_reader_read(xr->kvrd, &value, sizeof(value));
- if (ret)
- return ret;
- }
-
- value.size = le32toh(value.size);
-
- if (SZ_ADD_OV(sizeof(*out), value.size, &size) ||
- SZ_ADD_OV(size, 1, &size)) {
- return SQFS_ERROR_OVERFLOW;
- }
-
- out = calloc(1, size);
- if (out == NULL)
- return SQFS_ERROR_ALLOC;
-
- *out = value;
-
- ret = sqfs_meta_reader_read(xr->kvrd, out->value, value.size);
- if (ret)
- goto fail;
-
- if (key->type & SQFS_XATTR_FLAG_OOL) {
- ret = sqfs_meta_reader_seek(xr->kvrd, start, offset);
- if (ret)
- goto fail;
- }
-
- *val_out = out;
- return 0;
-fail:
- free(out);
- return ret;
-}
-
-int sqfs_xattr_reader_seek_kv(sqfs_xattr_reader_t *xr,
- const sqfs_xattr_id_t *desc)
-{
- sqfs_u32 offset = desc->xattr & 0xFFFF;
- sqfs_u64 block = xr->xattr_start + (desc->xattr >> 16);
-
- return sqfs_meta_reader_seek(xr->kvrd, block, offset);
-}
-
-int sqfs_xattr_reader_get_desc(sqfs_xattr_reader_t *xr, sqfs_u32 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)
- return idx == 0 ? 0 : SQFS_ERROR_OUT_OF_BOUNDS;
-
- if (idx >= xr->num_ids)
- return SQFS_ERROR_OUT_OF_BOUNDS;
-
- offset = (idx * sizeof(*desc)) % SQFS_META_BLOCK_SIZE;
- block = (idx * sizeof(*desc)) / SQFS_META_BLOCK_SIZE;
-
- ret = sqfs_meta_reader_seek(xr->idrd, xr->id_block_starts[block],
- offset);
- if (ret)
- return ret;
-
- 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;
-}
-
-sqfs_xattr_reader_t *sqfs_xattr_reader_create(sqfs_u32 flags)
-{
- sqfs_xattr_reader_t *xr;
-
- if (flags != 0)
- return NULL;
-
- xr = calloc(1, sizeof(*xr));
- if (xr == NULL)
- return NULL;
-
- sqfs_object_init(xr, xattr_reader_destroy, xattr_reader_copy);
- return xr;
-}
diff --git a/lib/sqfs/xattr/xattr_writer.c b/lib/sqfs/xattr/xattr_writer.c
deleted file mode 100644
index 39e1b05..0000000
--- a/lib/sqfs/xattr/xattr_writer.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * xattr_writer.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "xattr_writer.h"
-
-static sqfs_object_t *xattr_writer_copy(const sqfs_object_t *obj)
-{
- const sqfs_xattr_writer_t *xwr = (const sqfs_xattr_writer_t *)obj;
- sqfs_xattr_writer_t *copy;
- kv_block_desc_t *it;
-
- copy = calloc(1, sizeof(*copy));
- if (copy == NULL)
- return NULL;
-
- memcpy(copy, xwr, sizeof(*xwr));
-
- if (str_table_copy(&copy->keys, &xwr->keys))
- goto fail_keys;
-
- if (str_table_copy(&copy->values, &xwr->values))
- goto fail_values;
-
- if (array_init_copy(&copy->kv_pairs, &xwr->kv_pairs))
- goto fail_pairs;
-
- if (rbtree_copy(&xwr->kv_block_tree, &copy->kv_block_tree) != 0)
- goto fail_tree;
-
- for (it = xwr->kv_block_first; it != NULL; it = it->next) {
- rbtree_node_t *n = rbtree_lookup(&copy->kv_block_tree, it);
-
- if (copy->kv_block_last == NULL) {
- copy->kv_block_first = rbtree_node_key(n);
- copy->kv_block_last = copy->kv_block_first;
- } else {
- copy->kv_block_last->next = rbtree_node_key(n);
- copy->kv_block_last = copy->kv_block_last->next;
- }
-
- copy->kv_block_last->next = NULL;
- }
-
- return (sqfs_object_t *)copy;
-fail_tree:
- array_cleanup(&copy->kv_pairs);
-fail_pairs:
- str_table_cleanup(&copy->values);
-fail_values:
- str_table_cleanup(&copy->keys);
-fail_keys:
- free(copy);
- return NULL;
-}
-
-static void xattr_writer_destroy(sqfs_object_t *obj)
-{
- sqfs_xattr_writer_t *xwr = (sqfs_xattr_writer_t *)obj;
-
- rbtree_cleanup(&xwr->kv_block_tree);
- array_cleanup(&xwr->kv_pairs);
- str_table_cleanup(&xwr->values);
- str_table_cleanup(&xwr->keys);
- free(xwr);
-}
-
-static int block_compare(const void *context,
- const void *lhs, const void *rhs)
-{
- const sqfs_xattr_writer_t *xwr = context;
- const kv_block_desc_t *l = lhs, *r = rhs;
-
- if (l->count != r->count)
- return l->count < r->count ? -1 : 1;
-
- if (l->start == r->start)
- return 0;
-
- return memcmp((sqfs_u64 *)xwr->kv_pairs.data + l->start,
- (sqfs_u64 *)xwr->kv_pairs.data + r->start,
- l->count * xwr->kv_pairs.size);
-}
-
-sqfs_xattr_writer_t *sqfs_xattr_writer_create(sqfs_u32 flags)
-{
- sqfs_xattr_writer_t *xwr;
-
- if (flags != 0)
- return NULL;
-
- xwr = calloc(1, sizeof(*xwr));
- if (xwr == NULL)
- return NULL;
-
- sqfs_object_init(xwr, xattr_writer_destroy, xattr_writer_copy);
-
- if (str_table_init(&xwr->keys))
- goto fail_keys;
-
- if (str_table_init(&xwr->values))
- goto fail_values;
-
- if (array_init(&xwr->kv_pairs, sizeof(sqfs_u64),
- XATTR_INITIAL_PAIR_CAP)) {
- goto fail_pairs;
- }
-
- if (rbtree_init(&xwr->kv_block_tree, sizeof(kv_block_desc_t),
- sizeof(sqfs_u32), block_compare)) {
- goto fail_tree;
- }
-
- xwr->kv_block_tree.key_context = xwr;
- return xwr;
-fail_tree:
- array_cleanup(&xwr->kv_pairs);
-fail_pairs:
- str_table_cleanup(&xwr->values);
-fail_values:
- str_table_cleanup(&xwr->keys);
-fail_keys:
- free(xwr);
- return NULL;
-}
diff --git a/lib/sqfs/xattr/xattr_writer.h b/lib/sqfs/xattr/xattr_writer.h
deleted file mode 100644
index 792cfae..0000000
--- a/lib/sqfs/xattr/xattr_writer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * xattr_writer.h
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#ifndef XATTR_WRITER_H
-#define XATTR_WRITER_H
-
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include "sqfs/xattr_writer.h"
-#include "sqfs/meta_writer.h"
-#include "sqfs/super.h"
-#include "sqfs/xattr.h"
-#include "sqfs/error.h"
-#include "sqfs/block.h"
-#include "sqfs/io.h"
-
-#include "util/str_table.h"
-#include "util/rbtree.h"
-#include "util/array.h"
-#include "util/util.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-
-#define XATTR_INITIAL_PAIR_CAP 128
-
-#define MK_PAIR(key, value) (((sqfs_u64)(key) << 32UL) | (sqfs_u64)(value))
-#define GET_KEY(pair) ((pair >> 32UL) & 0x0FFFFFFFFUL)
-#define GET_VALUE(pair) (pair & 0x0FFFFFFFFUL)
-
-
-typedef struct kv_block_desc_t {
- struct kv_block_desc_t *next;
- size_t start;
- size_t count;
-
- sqfs_u64 start_ref;
- size_t size_bytes;
-} kv_block_desc_t;
-
-struct sqfs_xattr_writer_t {
- sqfs_object_t base;
-
- str_table_t keys;
- str_table_t values;
-
- array_t kv_pairs;
-
- size_t kv_start;
-
- rbtree_t kv_block_tree;
- kv_block_desc_t *kv_block_first;
- kv_block_desc_t *kv_block_last;
- size_t num_blocks;
-};
-
-#endif /* XATTR_WRITER_H */
diff --git a/lib/sqfs/xattr/xattr_writer_flush.c b/lib/sqfs/xattr/xattr_writer_flush.c
deleted file mode 100644
index a06463f..0000000
--- a/lib/sqfs/xattr/xattr_writer_flush.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * xattr_writer_flush.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "xattr_writer.h"
-
-static const char *hexmap = "0123456789ABCDEF";
-
-static void *from_base32(const char *input, size_t *size_out)
-{
- sqfs_u8 lo, hi, *out, *ptr;
- size_t len;
-
- len = strlen(input);
- *size_out = len / 2;
-
- out = malloc(*size_out);
- if (out == NULL)
- return NULL;
-
- ptr = out;
-
- while (*input != '\0') {
- lo = strchr(hexmap, *(input++)) - hexmap;
- hi = strchr(hexmap, *(input++)) - hexmap;
-
- *(ptr++) = lo | (hi << 4);
- }
-
- return out;
-}
-
-static sqfs_s32 write_key(sqfs_meta_writer_t *mw, const char *key,
- bool value_is_ool)
-{
- sqfs_xattr_entry_t kent;
- int type, err;
- size_t len;
-
- type = sqfs_get_xattr_prefix_id(key);
- assert(type >= 0);
-
- key = strchr(key, '.');
- assert(key != NULL);
- ++key;
- len = strlen(key);
-
- if (value_is_ool)
- type |= SQFS_XATTR_FLAG_OOL;
-
- memset(&kent, 0, sizeof(kent));
- kent.type = htole16(type);
- kent.size = htole16(len);
-
- err = sqfs_meta_writer_append(mw, &kent, sizeof(kent));
- if (err)
- return err;
-
- err = sqfs_meta_writer_append(mw, key, len);
- if (err)
- return err;
-
- return sizeof(kent) + len;
-}
-
-static sqfs_s32 write_value(sqfs_meta_writer_t *mw, const char *value_str,
- sqfs_u64 *value_ref_out)
-{
- sqfs_xattr_value_t vent;
- sqfs_u32 offset;
- sqfs_u64 block;
- size_t size;
- void *value;
- int err;
-
- value = from_base32(value_str, &size);
- if (value == NULL)
- return SQFS_ERROR_ALLOC;
-
- memset(&vent, 0, sizeof(vent));
- vent.size = htole32(size);
-
- sqfs_meta_writer_get_position(mw, &block, &offset);
- *value_ref_out = (block << 16) | (offset & 0xFFFF);
-
- err = sqfs_meta_writer_append(mw, &vent, sizeof(vent));
- if (err)
- goto fail;
-
- err = sqfs_meta_writer_append(mw, value, size);
- if (err)
- goto fail;
-
- free(value);
- return sizeof(vent) + size;
-fail:
- free(value);
- return err;
-}
-
-static sqfs_s32 write_value_ool(sqfs_meta_writer_t *mw, sqfs_u64 location)
-{
- sqfs_xattr_value_t vent;
- sqfs_u64 ref;
- int err;
-
- memset(&vent, 0, sizeof(vent));
- vent.size = htole32(sizeof(location));
- ref = htole64(location);
-
- err = sqfs_meta_writer_append(mw, &vent, sizeof(vent));
- if (err)
- return err;
-
- err = sqfs_meta_writer_append(mw, &ref, sizeof(ref));
- if (err)
- return err;
-
- return sizeof(vent) + sizeof(ref);
-}
-
-static bool should_store_ool(const char *val_str, size_t refcount)
-{
- if (refcount < 2)
- return false;
-
- /*
- Storing in line needs this many bytes: refcount * len
-
- Storing out-of-line needs this many: len + (refcount - 1) * 8
-
- Out-of-line prefereable iff refcount > 1 and:
- refcount * len > len + (refcount - 1) * 8
- => refcount * len - len > (refcount - 1) * 8
- => (refcount - 1) * len > (refcount - 1) * 8
- => len > 8
- */
- return (strlen(val_str) / 2) > sizeof(sqfs_u64);
-}
-
-static int write_block_pairs(const sqfs_xattr_writer_t *xwr,
- sqfs_meta_writer_t *mw,
- const kv_block_desc_t *blk,
- sqfs_u64 *ool_locations)
-{
- const char *key_str, *value_str;
- sqfs_s32 diff, total = 0;
- size_t i, refcount;
- sqfs_u64 ref;
-
- for (i = 0; i < blk->count; ++i) {
- sqfs_u64 ent = ((sqfs_u64 *)xwr->kv_pairs.data)[blk->start + i];
- sqfs_u32 key_idx = GET_KEY(ent);
- sqfs_u32 val_idx = GET_VALUE(ent);
-
- key_str = str_table_get_string(&xwr->keys, key_idx);
- value_str = str_table_get_string(&xwr->values, val_idx);
-
- if (ool_locations[val_idx] == 0xFFFFFFFFFFFFFFFFUL) {
- diff = write_key(mw, key_str, false);
- if (diff < 0)
- return diff;
- total += diff;
-
- diff = write_value(mw, value_str, &ref);
- if (diff < 0)
- return diff;
- total += diff;
-
- refcount = str_table_get_ref_count(&xwr->values,
- val_idx);
-
- if (should_store_ool(value_str, refcount))
- ool_locations[val_idx] = ref;
- } else {
- diff = write_key(mw, key_str, true);
- if (diff < 0)
- return diff;
- total += diff;
-
- diff = write_value_ool(mw, ool_locations[val_idx]);
- if (diff < 0)
- return diff;
- total += diff;
- }
- }
-
- return total;
-}
-
-static int write_kv_pairs(const sqfs_xattr_writer_t *xwr,
- sqfs_meta_writer_t *mw)
-{
- sqfs_u64 block, *ool_locations;
- kv_block_desc_t *blk;
- sqfs_u32 offset;
- sqfs_s32 size;
- size_t i;
-
- ool_locations = alloc_array(sizeof(ool_locations[0]),
- str_table_count(&xwr->values));
- if (ool_locations == NULL)
- return SQFS_ERROR_ALLOC;
-
- for (i = 0; i < str_table_count(&xwr->values); ++i)
- ool_locations[i] = 0xFFFFFFFFFFFFFFFFUL;
-
- for (blk = xwr->kv_block_first; blk != NULL; blk = blk->next) {
- sqfs_meta_writer_get_position(mw, &block, &offset);
- blk->start_ref = (block << 16) | (offset & 0xFFFF);
-
- size = write_block_pairs(xwr, mw, blk, ool_locations);
- if (size < 0) {
- free(ool_locations);
- return size;
- }
-
- blk->size_bytes = size;
- }
-
- free(ool_locations);
- return sqfs_meta_writer_flush(mw);
-}
-
-static int write_id_table(const sqfs_xattr_writer_t *xwr,
- sqfs_meta_writer_t *mw,
- sqfs_u64 *locations)
-{
- sqfs_xattr_id_t id_ent;
- kv_block_desc_t *blk;
- sqfs_u32 offset;
- sqfs_u64 block;
- size_t i = 0;
- int err;
-
- locations[i++] = 0;
-
- for (blk = xwr->kv_block_first; blk != NULL; blk = blk->next) {
- memset(&id_ent, 0, sizeof(id_ent));
- id_ent.xattr = htole64(blk->start_ref);
- id_ent.count = htole32(blk->count);
- id_ent.size = htole32(blk->size_bytes);
-
- err = sqfs_meta_writer_append(mw, &id_ent, sizeof(id_ent));
- if (err)
- return err;
-
- sqfs_meta_writer_get_position(mw, &block, &offset);
- if (block != locations[i - 1])
- locations[i++] = block;
- }
-
- return sqfs_meta_writer_flush(mw);
-}
-
-static int write_location_table(const sqfs_xattr_writer_t *xwr,
- sqfs_u64 kv_start, sqfs_file_t *file,
- const sqfs_super_t *super, sqfs_u64 *locations,
- size_t loc_count)
-{
- sqfs_xattr_id_table_t idtbl;
- int err;
-
- memset(&idtbl, 0, sizeof(idtbl));
- idtbl.xattr_table_start = htole64(kv_start);
- idtbl.xattr_ids = htole32(xwr->num_blocks);
-
- err = file->write_at(file, super->xattr_id_table_start,
- &idtbl, sizeof(idtbl));
- if (err)
- return err;
-
- return file->write_at(file, super->xattr_id_table_start + sizeof(idtbl),
- locations, sizeof(locations[0]) * loc_count);
-}
-
-static int alloc_location_table(const sqfs_xattr_writer_t *xwr,
- sqfs_u64 **tbl_out, size_t *szout)
-{
- sqfs_u64 *locations;
- size_t size, count;
-
- if (SZ_MUL_OV(xwr->num_blocks, sizeof(sqfs_xattr_id_t), &size))
- return SQFS_ERROR_OVERFLOW;
-
- count = size / SQFS_META_BLOCK_SIZE;
- if (size % SQFS_META_BLOCK_SIZE)
- ++count;
-
- locations = alloc_array(sizeof(sqfs_u64), count);
- if (locations == NULL)
- return SQFS_ERROR_ALLOC;
-
- *tbl_out = locations;
- *szout = count;
- return 0;
-}
-
-int sqfs_xattr_writer_flush(const sqfs_xattr_writer_t *xwr, sqfs_file_t *file,
- sqfs_super_t *super, sqfs_compressor_t *cmp)
-{
- sqfs_u64 *locations = NULL, kv_start, id_start;
- sqfs_meta_writer_t *mw;
- size_t i, count;
- int err;
-
- if (xwr->kv_pairs.used == 0 || xwr->num_blocks == 0) {
- super->xattr_id_table_start = 0xFFFFFFFFFFFFFFFFUL;
- super->flags |= SQFS_FLAG_NO_XATTRS;
- return 0;
- }
-
- mw = sqfs_meta_writer_create(file, cmp, 0);
- if (mw == NULL)
- return SQFS_ERROR_ALLOC;
-
- kv_start = file->get_size(file);
- err = write_kv_pairs(xwr, mw);
- if (err)
- goto out;
-
- sqfs_meta_writer_reset(mw);
-
- id_start = file->get_size(file);
- err = alloc_location_table(xwr, &locations, &count);
- if (err)
- goto out;
-
- err = write_id_table(xwr, mw, locations);
- if (err)
- goto out;
-
- super->xattr_id_table_start = file->get_size(file);
- super->flags &= ~SQFS_FLAG_NO_XATTRS;
-
- for (i = 0; i < count; ++i)
- locations[i] = htole64(locations[i] + id_start);
-
- err = write_location_table(xwr, kv_start, file, super,
- locations, count);
-out:
- free(locations);
- sqfs_drop(mw);
- return err;
-}
diff --git a/lib/sqfs/xattr/xattr_writer_record.c b/lib/sqfs/xattr/xattr_writer_record.c
deleted file mode 100644
index 81bbf6b..0000000
--- a/lib/sqfs/xattr/xattr_writer_record.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * xattr_writer_record.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "xattr_writer.h"
-
-static const char *hexmap = "0123456789ABCDEF";
-
-static char *to_base32(const void *input, size_t size)
-{
- const sqfs_u8 *in = input;
- char *out, *ptr;
- size_t i;
-
- out = malloc(2 * size + 1);
- if (out == NULL)
- return NULL;
-
- ptr = out;
-
- for (i = 0; i < size; ++i) {
- *(ptr++) = hexmap[ in[i] & 0x0F];
- *(ptr++) = hexmap[(in[i] >> 4) & 0x0F];
- }
-
- *ptr = '\0';
- return out;
-}
-
-static int compare_u64(const void *a, const void *b)
-{
- sqfs_u64 lhs = *((const sqfs_u64 *)a);
- sqfs_u64 rhs = *((const sqfs_u64 *)b);
-
- return (lhs < rhs ? -1 : (lhs > rhs ? 1 : 0));
-}
-
-int sqfs_xattr_writer_begin(sqfs_xattr_writer_t *xwr, sqfs_u32 flags)
-{
- if (flags != 0)
- return SQFS_ERROR_UNSUPPORTED;
-
- xwr->kv_start = xwr->kv_pairs.used;
- return 0;
-}
-
-int sqfs_xattr_writer_add(sqfs_xattr_writer_t *xwr, const char *key,
- const void *value, size_t size)
-{
- size_t i, key_index, old_value_index, value_index;
- sqfs_u64 kv_pair;
- char *value_str;
- int err;
-
- if (sqfs_get_xattr_prefix_id(key) < 0)
- return SQFS_ERROR_UNSUPPORTED;
-
- err = str_table_get_index(&xwr->keys, key, &key_index);
- if (err)
- return err;
-
- value_str = to_base32(value, size);
- if (value_str == NULL)
- return SQFS_ERROR_ALLOC;
-
- err = str_table_get_index(&xwr->values, value_str, &value_index);
- free(value_str);
- if (err)
- return err;
-
- str_table_add_ref(&xwr->values, value_index);
-
- if (sizeof(size_t) > sizeof(sqfs_u32)) {
- if (key_index > 0x0FFFFFFFFUL || value_index > 0x0FFFFFFFFUL)
- return SQFS_ERROR_OVERFLOW;
- }
-
- kv_pair = MK_PAIR(key_index, value_index);
-
- for (i = xwr->kv_start; i < xwr->kv_pairs.used; ++i) {
- sqfs_u64 ent = ((sqfs_u64 *)xwr->kv_pairs.data)[i];
-
- if (ent == kv_pair)
- return 0;
-
- if (GET_KEY(ent) == key_index) {
- old_value_index = GET_VALUE(ent);
-
- str_table_del_ref(&xwr->values, old_value_index);
-
- ((sqfs_u64 *)xwr->kv_pairs.data)[i] = kv_pair;
- return 0;
- }
- }
-
- return array_append(&xwr->kv_pairs, &kv_pair);
-}
-
-int sqfs_xattr_writer_end(sqfs_xattr_writer_t *xwr, sqfs_u32 *out)
-{
- kv_block_desc_t blk;
- rbtree_node_t *n;
- sqfs_u32 index;
- int ret;
-
- memset(&blk, 0, sizeof(blk));
- blk.start = xwr->kv_start;
- blk.count = xwr->kv_pairs.used - xwr->kv_start;
-
- if (blk.count == 0) {
- *out = 0xFFFFFFFF;
- return 0;
- }
-
- array_sort_range(&xwr->kv_pairs, blk.start, blk.count, compare_u64);
-
- n = rbtree_lookup(&xwr->kv_block_tree, &blk);
-
- if (n != NULL) {
- index = *((sqfs_u32 *)rbtree_node_value(n));
- xwr->kv_pairs.used = xwr->kv_start;
- } else {
- index = xwr->num_blocks;
-
- ret = rbtree_insert(&xwr->kv_block_tree, &blk, &index);
- if (ret != 0)
- return ret;
-
- xwr->num_blocks += 1;
- n = rbtree_lookup(&xwr->kv_block_tree, &blk);
-
- if (xwr->kv_block_last == NULL) {
- xwr->kv_block_first = rbtree_node_key(n);
- xwr->kv_block_last = xwr->kv_block_first;
- } else {
- xwr->kv_block_last->next = rbtree_node_key(n);
- xwr->kv_block_last = xwr->kv_block_last->next;
- }
- }
-
- *out = index;
- return 0;
-}