aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/src/id_table.c
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-01-31 11:21:30 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-01-31 13:51:49 +0100
commitcdccc69c62579b0c13b35fad0728079652b8f3c9 (patch)
tree9fa54c710f73c5e08a9c8466e7a712eb63ee07ac /lib/sqfs/src/id_table.c
parent2182129c8f359c4fa1390eaba7a65b595ccd4182 (diff)
Move library source into src sub-directory
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/src/id_table.c')
-rw-r--r--lib/sqfs/src/id_table.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/lib/sqfs/src/id_table.c b/lib/sqfs/src/id_table.c
new file mode 100644
index 0000000..ec3fdfe
--- /dev/null
+++ b/lib/sqfs/src/id_table.c
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: LGPL-3.0-or-later */
+/*
+ * id_table.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#define SQFS_BUILDING_DLL
+#include "config.h"
+
+#include "sqfs/id_table.h"
+#include "sqfs/super.h"
+#include "sqfs/table.h"
+#include "sqfs/error.h"
+#include "compat.h"
+#include "util/array.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+struct sqfs_id_table_t {
+ sqfs_object_t base;
+
+ array_t ids;
+};
+
+static void id_table_destroy(sqfs_object_t *obj)
+{
+ sqfs_id_table_t *tbl = (sqfs_id_table_t *)obj;
+
+ array_cleanup(&tbl->ids);
+ free(tbl);
+}
+
+static sqfs_object_t *id_table_copy(const sqfs_object_t *obj)
+{
+ const sqfs_id_table_t *tbl = (const sqfs_id_table_t *)obj;
+ sqfs_id_table_t *copy = calloc(1, sizeof(*copy));
+
+ if (copy == NULL)
+ return NULL;
+
+ if (array_init_copy(&copy->ids, &tbl->ids) != 0) {
+ free(copy);
+ return NULL;
+ }
+
+ return (sqfs_object_t *)copy;
+}
+
+sqfs_id_table_t *sqfs_id_table_create(sqfs_u32 flags)
+{
+ sqfs_id_table_t *tbl;
+
+ if (flags != 0)
+ return NULL;
+
+ tbl = calloc(1, sizeof(sqfs_id_table_t));
+
+ if (tbl != NULL) {
+ array_init(&tbl->ids, sizeof(sqfs_u32), 0);
+ sqfs_object_init(tbl, id_table_destroy, id_table_copy);
+ }
+
+ return tbl;
+}
+
+int sqfs_id_table_id_to_index(sqfs_id_table_t *tbl, sqfs_u32 id, sqfs_u16 *out)
+{
+ size_t i;
+
+ for (i = 0; i < tbl->ids.used; ++i) {
+ if (((sqfs_u32 *)tbl->ids.data)[i] == id) {
+ *out = i;
+ return 0;
+ }
+ }
+
+ if (tbl->ids.used == 0x10000)
+ return SQFS_ERROR_OVERFLOW;
+
+ *out = tbl->ids.used;
+ return array_append(&tbl->ids, &id);
+}
+
+int sqfs_id_table_index_to_id(const sqfs_id_table_t *tbl, sqfs_u16 index,
+ sqfs_u32 *out)
+{
+ if (index >= tbl->ids.used)
+ return SQFS_ERROR_OUT_OF_BOUNDS;
+
+ *out = ((sqfs_u32 *)tbl->ids.data)[index];
+ return 0;
+}
+
+int sqfs_id_table_read(sqfs_id_table_t *tbl, sqfs_file_t *file,
+ const sqfs_super_t *super, sqfs_compressor_t *cmp)
+{
+ sqfs_u64 upper_limit, lower_limit;
+ void *raw_ids;
+ size_t i;
+ int ret;
+
+ if (!super->id_count || super->id_table_start >= super->bytes_used)
+ return SQFS_ERROR_CORRUPTED;
+
+ upper_limit = super->id_table_start;
+ lower_limit = super->directory_table_start;
+
+ if (super->fragment_table_start > lower_limit &&
+ super->fragment_table_start < upper_limit) {
+ lower_limit = super->fragment_table_start;
+ }
+
+ if (super->export_table_start > lower_limit &&
+ super->export_table_start < upper_limit) {
+ lower_limit = super->export_table_start;
+ }
+
+ array_cleanup(&tbl->ids);
+ tbl->ids.size = sizeof(sqfs_u32);
+
+ ret = sqfs_read_table(file, cmp, super->id_count * sizeof(sqfs_u32),
+ super->id_table_start, lower_limit,
+ upper_limit, &raw_ids);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < super->id_count; ++i)
+ ((sqfs_u32 *)raw_ids)[i] = le32toh(((sqfs_u32 *)raw_ids)[i]);
+
+ tbl->ids.data = raw_ids;
+ tbl->ids.used = super->id_count;
+ tbl->ids.count = super->id_count;
+ return 0;
+}
+
+int sqfs_id_table_write(sqfs_id_table_t *tbl, sqfs_file_t *file,
+ sqfs_super_t *super, sqfs_compressor_t *cmp)
+{
+ sqfs_u64 start;
+ size_t i;
+ int ret;
+
+ for (i = 0; i < tbl->ids.used; ++i) {
+ ((sqfs_u32 *)tbl->ids.data)[i] =
+ htole32(((sqfs_u32 *)tbl->ids.data)[i]);
+ }
+
+ super->id_count = tbl->ids.used;
+
+ ret = sqfs_write_table(file, cmp, tbl->ids.data,
+ sizeof(sqfs_u32) * tbl->ids.used, &start);
+
+ super->id_table_start = start;
+
+ for (i = 0; i < tbl->ids.used; ++i) {
+ ((sqfs_u32 *)tbl->ids.data)[i] =
+ le32toh(((sqfs_u32 *)tbl->ids.data)[i]);
+ }
+
+ return ret;
+}