diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sqfs/Makemodule.am | 11 | ||||
-rw-r--r-- | lib/sqfs/xattr/xattr.c (renamed from lib/sqfs/xattr.c) | 0 | ||||
-rw-r--r-- | lib/sqfs/xattr/xattr_reader.c (renamed from lib/sqfs/xattr_reader.c) | 0 | ||||
-rw-r--r-- | lib/sqfs/xattr/xattr_writer.c | 110 | ||||
-rw-r--r-- | lib/sqfs/xattr/xattr_writer.h | 63 | ||||
-rw-r--r-- | lib/sqfs/xattr/xattr_writer_flush.c (renamed from lib/sqfs/xattr_writer.c) | 333 | ||||
-rw-r--r-- | lib/sqfs/xattr/xattr_writer_record.c | 179 |
7 files changed, 361 insertions, 335 deletions
diff --git a/lib/sqfs/Makemodule.am b/lib/sqfs/Makemodule.am index 61c9b09..85f4aad 100644 --- a/lib/sqfs/Makemodule.am +++ b/lib/sqfs/Makemodule.am @@ -11,15 +11,18 @@ LIBSQFS_HEARDS = include/sqfs/meta_writer.h \ include/sqfs/frag_table.h include/sqfs/block_writer.h libsquashfs_la_SOURCES = $(LIBSQFS_HEARDS) lib/sqfs/id_table.c lib/sqfs/super.c -libsquashfs_la_SOURCES += lib/sqfs/readdir.c lib/sqfs/xattr.c +libsquashfs_la_SOURCES += lib/sqfs/readdir.c lib/sqfs/xattr/xattr.c libsquashfs_la_SOURCES += lib/sqfs/write_table.c lib/sqfs/meta_writer.c libsquashfs_la_SOURCES += lib/sqfs/read_super.c lib/sqfs/meta_reader.c libsquashfs_la_SOURCES += lib/sqfs/read_inode.c lib/sqfs/write_inode.c -libsquashfs_la_SOURCES += lib/sqfs/dir_writer.c lib/sqfs/xattr_reader.c +libsquashfs_la_SOURCES += lib/sqfs/dir_writer.c lib/sqfs/xattr/xattr_reader.c libsquashfs_la_SOURCES += lib/sqfs/read_table.c lib/sqfs/comp/compressor.c -libsquashfs_la_SOURCES += lib/sqfs/comp/internal.h lib/sqfs/xattr_writer.c +libsquashfs_la_SOURCES += lib/sqfs/comp/internal.h libsquashfs_la_SOURCES += lib/sqfs/dir_reader.c lib/sqfs/read_tree.c -libsquashfs_la_SOURCES += lib/sqfs/inode.c +libsquashfs_la_SOURCES += lib/sqfs/inode.c lib/sqfs/xattr/xattr_writer.c +libsquashfs_la_SOURCES += lib/sqfs/xattr/xattr_writer_flush.c +libsquashfs_la_SOURCES += lib/sqfs/xattr/xattr_writer_record.c +libsquashfs_la_SOURCES += lib/sqfs/xattr/xattr_writer.h libsquashfs_la_SOURCES += lib/sqfs/write_super.c lib/sqfs/data_reader.c libsquashfs_la_SOURCES += lib/sqfs/block_processor/internal.h libsquashfs_la_SOURCES += lib/sqfs/block_processor/common.c diff --git a/lib/sqfs/xattr.c b/lib/sqfs/xattr/xattr.c index 29ecebf..29ecebf 100644 --- a/lib/sqfs/xattr.c +++ b/lib/sqfs/xattr/xattr.c diff --git a/lib/sqfs/xattr_reader.c b/lib/sqfs/xattr/xattr_reader.c index 37f222a..37f222a 100644 --- a/lib/sqfs/xattr_reader.c +++ b/lib/sqfs/xattr/xattr_reader.c diff --git a/lib/sqfs/xattr/xattr_writer.c b/lib/sqfs/xattr/xattr_writer.c new file mode 100644 index 0000000..9de3823 --- /dev/null +++ b/lib/sqfs/xattr/xattr_writer.c @@ -0,0 +1,110 @@ +/* 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; + kv_block_desc_t *blk, *it, **next; + sqfs_xattr_writer_t *copy; + + copy = calloc(1, sizeof(*copy)); + if (copy == NULL) + return NULL; + + memcpy(copy, xwr, sizeof(*xwr)); + + if (str_table_copy(©->keys, &xwr->keys)) + goto fail_keys; + + if (str_table_copy(©->values, &xwr->values)) + goto fail_values; + + copy->max_pairs = xwr->num_pairs; + copy->num_pairs = xwr->num_pairs; + + copy->kv_pairs = malloc(sizeof(copy->kv_pairs[0]) * xwr->num_pairs); + if (copy->kv_pairs == NULL) + goto fail_pairs; + + memcpy(copy->kv_pairs, xwr->kv_pairs, + sizeof(copy->kv_pairs[0]) * xwr->num_pairs); + + next = &(copy->kv_blocks); + + for (it = xwr->kv_blocks; it != NULL; it = it->next) { + blk = malloc(sizeof(*blk)); + if (blk == NULL) + goto fail_blk; + + memcpy(blk, it, sizeof(*it)); + blk->next = NULL; + + *next = blk; + next = &(blk->next); + } + + return (sqfs_object_t *)copy; +fail_blk: + while (copy->kv_blocks != NULL) { + blk = copy->kv_blocks; + copy->kv_blocks = copy->kv_blocks->next; + free(blk); + } +fail_pairs: + str_table_cleanup(©->values); +fail_values: + str_table_cleanup(©->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; + kv_block_desc_t *blk; + + while (xwr->kv_blocks != NULL) { + blk = xwr->kv_blocks; + xwr->kv_blocks = xwr->kv_blocks->next; + free(blk); + } + + free(xwr->kv_pairs); + str_table_cleanup(&xwr->values); + str_table_cleanup(&xwr->keys); + free(xwr); +} + +sqfs_xattr_writer_t *sqfs_xattr_writer_create(void) +{ + sqfs_xattr_writer_t *xwr = calloc(1, sizeof(*xwr)); + + if (str_table_init(&xwr->keys, XATTR_KEY_BUCKETS)) + goto fail_keys; + + if (str_table_init(&xwr->values, XATTR_VALUE_BUCKETS)) + goto fail_values; + + xwr->max_pairs = XATTR_INITIAL_PAIR_CAP; + xwr->kv_pairs = alloc_array(sizeof(xwr->kv_pairs[0]), xwr->max_pairs); + + if (xwr->kv_pairs == NULL) + goto fail_pairs; + + ((sqfs_object_t *)xwr)->copy = xattr_writer_copy; + ((sqfs_object_t *)xwr)->destroy = xattr_writer_destroy; + return xwr; +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 new file mode 100644 index 0000000..826b6f6 --- /dev/null +++ b/lib/sqfs/xattr/xattr_writer.h @@ -0,0 +1,63 @@ +/* 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 "str_table.h" +#include "util.h" + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + + +#define XATTR_KEY_BUCKETS 31 +#define XATTR_VALUE_BUCKETS 511 +#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; + + sqfs_u64 *kv_pairs; + size_t max_pairs; + size_t num_pairs; + + size_t kv_start; + + kv_block_desc_t *kv_blocks; + size_t num_blocks; +}; + +#endif /* XATTR_WRITER_H */ diff --git a/lib/sqfs/xattr_writer.c b/lib/sqfs/xattr/xattr_writer_flush.c index 488fd43..9b3de30 100644 --- a/lib/sqfs/xattr_writer.c +++ b/lib/sqfs/xattr/xattr_writer_flush.c @@ -1,60 +1,13 @@ /* SPDX-License-Identifier: LGPL-3.0-or-later */ /* - * xattr_writer.c + * xattr_writer_flush.c * * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> */ -#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 "str_table.h" -#include "util.h" - -#include <stdlib.h> -#include <string.h> -#include <assert.h> - - -#define XATTR_KEY_BUCKETS 31 -#define XATTR_VALUE_BUCKETS 511 -#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) - +#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 void *from_base32(const char *input, size_t *size_out) { sqfs_u8 lo, hi, *out, *ptr; @@ -79,288 +32,6 @@ static void *from_base32(const char *input, size_t *size_out) 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)); -} - - - -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; - - sqfs_u64 *kv_pairs; - size_t max_pairs; - size_t num_pairs; - - size_t kv_start; - - kv_block_desc_t *kv_blocks; - size_t num_blocks; -}; - - -static sqfs_object_t *xattr_writer_copy(const sqfs_object_t *obj) -{ - const sqfs_xattr_writer_t *xwr = (const sqfs_xattr_writer_t *)obj; - kv_block_desc_t *blk, *it, **next; - sqfs_xattr_writer_t *copy; - - copy = calloc(1, sizeof(*copy)); - if (copy == NULL) - return NULL; - - memcpy(copy, xwr, sizeof(*xwr)); - - if (str_table_copy(©->keys, &xwr->keys)) - goto fail_keys; - - if (str_table_copy(©->values, &xwr->values)) - goto fail_values; - - copy->max_pairs = xwr->num_pairs; - copy->num_pairs = xwr->num_pairs; - - copy->kv_pairs = malloc(sizeof(copy->kv_pairs[0]) * xwr->num_pairs); - if (copy->kv_pairs == NULL) - goto fail_pairs; - - memcpy(copy->kv_pairs, xwr->kv_pairs, - sizeof(copy->kv_pairs[0]) * xwr->num_pairs); - - next = &(copy->kv_blocks); - - for (it = xwr->kv_blocks; it != NULL; it = it->next) { - blk = malloc(sizeof(*blk)); - if (blk == NULL) - goto fail_blk; - - memcpy(blk, it, sizeof(*it)); - blk->next = NULL; - - *next = blk; - next = &(blk->next); - } - - return (sqfs_object_t *)copy; -fail_blk: - while (copy->kv_blocks != NULL) { - blk = copy->kv_blocks; - copy->kv_blocks = copy->kv_blocks->next; - free(blk); - } -fail_pairs: - str_table_cleanup(©->values); -fail_values: - str_table_cleanup(©->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; - kv_block_desc_t *blk; - - while (xwr->kv_blocks != NULL) { - blk = xwr->kv_blocks; - xwr->kv_blocks = xwr->kv_blocks->next; - free(blk); - } - - free(xwr->kv_pairs); - str_table_cleanup(&xwr->values); - str_table_cleanup(&xwr->keys); - free(xwr); -} - -sqfs_xattr_writer_t *sqfs_xattr_writer_create(void) -{ - sqfs_xattr_writer_t *xwr = calloc(1, sizeof(*xwr)); - - if (str_table_init(&xwr->keys, XATTR_KEY_BUCKETS)) - goto fail_keys; - - if (str_table_init(&xwr->values, XATTR_VALUE_BUCKETS)) - goto fail_values; - - xwr->max_pairs = XATTR_INITIAL_PAIR_CAP; - xwr->kv_pairs = alloc_array(sizeof(xwr->kv_pairs[0]), xwr->max_pairs); - - if (xwr->kv_pairs == NULL) - goto fail_pairs; - - ((sqfs_object_t *)xwr)->copy = xattr_writer_copy; - ((sqfs_object_t *)xwr)->destroy = xattr_writer_destroy; - return xwr; -fail_pairs: - str_table_cleanup(&xwr->values); -fail_values: - str_table_cleanup(&xwr->keys); -fail_keys: - free(xwr); - return NULL; -} - -int sqfs_xattr_writer_begin(sqfs_xattr_writer_t *xwr) -{ - xwr->kv_start = xwr->num_pairs; - 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, new_count; - sqfs_u64 kv_pair, *new; - char *value_str; - int err; - - if (sqfs_get_xattr_prefix_id(key) < 0) - return SQFS_ERROR_UNSUPPORTED; - - /* resolve key and value into unique, incremental IDs */ - 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; - } - - /* bail if already have the pair, overwrite if we have the key */ - kv_pair = MK_PAIR(key_index, value_index); - - for (i = xwr->kv_start; i < xwr->num_pairs; ++i) { - if (xwr->kv_pairs[i] == kv_pair) - return 0; - - if (GET_KEY(xwr->kv_pairs[i]) == key_index) { - old_value_index = GET_VALUE(xwr->kv_pairs[i]); - - str_table_del_ref(&xwr->values, old_value_index); - - xwr->kv_pairs[i] = kv_pair; - return 0; - } - } - - /* append it to the list */ - if (xwr->max_pairs == xwr->num_pairs) { - new_count = xwr->max_pairs * 2; - new = realloc(xwr->kv_pairs, - sizeof(xwr->kv_pairs[0]) * new_count); - - if (new == NULL) - return SQFS_ERROR_ALLOC; - - xwr->kv_pairs = new; - xwr->max_pairs = new_count; - } - - xwr->kv_pairs[xwr->num_pairs++] = kv_pair; - return 0; -} - -int sqfs_xattr_writer_end(sqfs_xattr_writer_t *xwr, sqfs_u32 *out) -{ - kv_block_desc_t *blk, *blk_prev; - size_t i, count, value_idx; - sqfs_u32 index; - int ret; - - count = xwr->num_pairs - xwr->kv_start; - if (count == 0) { - *out = 0xFFFFFFFF; - return 0; - } - - qsort(xwr->kv_pairs + xwr->kv_start, count, - sizeof(xwr->kv_pairs[0]), compare_u64); - - blk_prev = NULL; - blk = xwr->kv_blocks; - index = 0; - - while (blk != NULL) { - if (blk->count == count) { - ret = memcmp(xwr->kv_pairs + blk->start, - xwr->kv_pairs + xwr->kv_start, - sizeof(xwr->kv_pairs[0]) * count); - - if (ret == 0) - break; - } - - if (index == 0xFFFFFFFF) - return SQFS_ERROR_OVERFLOW; - - ++index; - blk_prev = blk; - blk = blk->next; - } - - if (blk != NULL) { - for (i = 0; i < count; ++i) { - value_idx = GET_VALUE(xwr->kv_pairs[xwr->kv_start + i]); - str_table_del_ref(&xwr->values, value_idx); - - value_idx = GET_VALUE(xwr->kv_pairs[blk->start + i]); - str_table_add_ref(&xwr->values, value_idx); - } - - xwr->num_pairs = xwr->kv_start; - } else { - blk = calloc(1, sizeof(*blk)); - if (blk == NULL) - return SQFS_ERROR_ALLOC; - - blk->start = xwr->kv_start; - blk->count = count; - - if (blk_prev == NULL) { - xwr->kv_blocks = blk; - } else { - blk_prev->next = blk; - } - - xwr->num_blocks += 1; - } - - *out = index; - return 0; -} - -/*****************************************************************************/ - static sqfs_s32 write_key(sqfs_meta_writer_t *mw, const char *key, bool value_is_ool) { diff --git a/lib/sqfs/xattr/xattr_writer_record.c b/lib/sqfs/xattr/xattr_writer_record.c new file mode 100644 index 0000000..5e97868 --- /dev/null +++ b/lib/sqfs/xattr/xattr_writer_record.c @@ -0,0 +1,179 @@ +/* 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) +{ + xwr->kv_start = xwr->num_pairs; + 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, new_count; + sqfs_u64 kv_pair, *new; + char *value_str; + int err; + + if (sqfs_get_xattr_prefix_id(key) < 0) + return SQFS_ERROR_UNSUPPORTED; + + /* resolve key and value into unique, incremental IDs */ + 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; + } + + /* bail if already have the pair, overwrite if we have the key */ + kv_pair = MK_PAIR(key_index, value_index); + + for (i = xwr->kv_start; i < xwr->num_pairs; ++i) { + if (xwr->kv_pairs[i] == kv_pair) + return 0; + + if (GET_KEY(xwr->kv_pairs[i]) == key_index) { + old_value_index = GET_VALUE(xwr->kv_pairs[i]); + + str_table_del_ref(&xwr->values, old_value_index); + + xwr->kv_pairs[i] = kv_pair; + return 0; + } + } + + /* append it to the list */ + if (xwr->max_pairs == xwr->num_pairs) { + new_count = xwr->max_pairs * 2; + new = realloc(xwr->kv_pairs, + sizeof(xwr->kv_pairs[0]) * new_count); + + if (new == NULL) + return SQFS_ERROR_ALLOC; + + xwr->kv_pairs = new; + xwr->max_pairs = new_count; + } + + xwr->kv_pairs[xwr->num_pairs++] = kv_pair; + return 0; +} + +int sqfs_xattr_writer_end(sqfs_xattr_writer_t *xwr, sqfs_u32 *out) +{ + kv_block_desc_t *blk, *blk_prev; + size_t i, count, value_idx; + sqfs_u32 index; + int ret; + + count = xwr->num_pairs - xwr->kv_start; + if (count == 0) { + *out = 0xFFFFFFFF; + return 0; + } + + qsort(xwr->kv_pairs + xwr->kv_start, count, + sizeof(xwr->kv_pairs[0]), compare_u64); + + blk_prev = NULL; + blk = xwr->kv_blocks; + index = 0; + + while (blk != NULL) { + if (blk->count == count) { + ret = memcmp(xwr->kv_pairs + blk->start, + xwr->kv_pairs + xwr->kv_start, + sizeof(xwr->kv_pairs[0]) * count); + + if (ret == 0) + break; + } + + if (index == 0xFFFFFFFF) + return SQFS_ERROR_OVERFLOW; + + ++index; + blk_prev = blk; + blk = blk->next; + } + + if (blk != NULL) { + for (i = 0; i < count; ++i) { + value_idx = GET_VALUE(xwr->kv_pairs[xwr->kv_start + i]); + str_table_del_ref(&xwr->values, value_idx); + + value_idx = GET_VALUE(xwr->kv_pairs[blk->start + i]); + str_table_add_ref(&xwr->values, value_idx); + } + + xwr->num_pairs = xwr->kv_start; + } else { + blk = calloc(1, sizeof(*blk)); + if (blk == NULL) + return SQFS_ERROR_ALLOC; + + blk->start = xwr->kv_start; + blk->count = count; + + if (blk_prev == NULL) { + xwr->kv_blocks = blk; + } else { + blk_prev->next = blk; + } + + xwr->num_blocks += 1; + } + + *out = index; + return 0; +} |