aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/id_table.c
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-01 23:08:04 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-01 23:08:36 +0200
commit9d9d4505f58b6584fe3b261a7686c5d779f77c11 (patch)
tree7f1a086abc273c55c4d3a9cf96144715e3d15329 /lib/sqfs/id_table.c
parent307107ecd2fc3ffbf6fe91497daf767700f3572f (diff)
Internalize the layout of the id_table_t structure
As an opaque struct it has a chance to change its layout in the future without breaking ABI compatibiliy. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/id_table.c')
-rw-r--r--lib/sqfs/id_table.c99
1 files changed, 95 insertions, 4 deletions
diff --git a/lib/sqfs/id_table.c b/lib/sqfs/id_table.c
index 192cdbb..75d5db4 100644
--- a/lib/sqfs/id_table.c
+++ b/lib/sqfs/id_table.c
@@ -7,20 +7,32 @@
#include "config.h"
#include "sqfs/id_table.h"
+#include "sqfs/table.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
-int id_table_init(id_table_t *tbl)
+struct id_table_t {
+ uint32_t *ids;
+ size_t num_ids;
+ size_t max_ids;
+};
+
+id_table_t *id_table_create(void)
{
- memset(tbl, 0, sizeof(*tbl));
- return 0;
+ id_table_t *tbl = calloc(1, sizeof(*tbl));
+
+ if (tbl == NULL)
+ perror("Creating ID table");
+
+ return tbl;
}
-void id_table_cleanup(id_table_t *tbl)
+void id_table_destroy(id_table_t *tbl)
{
free(tbl->ids);
+ free(tbl);
}
int id_table_id_to_index(id_table_t *tbl, uint32_t id, uint16_t *out)
@@ -57,3 +69,82 @@ int id_table_id_to_index(id_table_t *tbl, uint32_t id, uint16_t *out)
tbl->ids[tbl->num_ids++] = id;
return 0;
}
+
+int id_table_index_to_id(const id_table_t *tbl, uint16_t index, uint32_t *out)
+{
+ if (index >= tbl->num_ids) {
+ fputs("attempted out of bounds ID table access\n", stderr);
+ return -1;
+ }
+
+ *out = tbl->ids[index];
+ return 0;
+}
+
+int id_table_read(id_table_t *tbl, int fd, sqfs_super_t *super,
+ compressor_t *cmp)
+{
+ uint64_t upper_limit, lower_limit;
+ size_t i;
+
+ if (tbl->ids != NULL) {
+ free(tbl->ids);
+ tbl->num_ids = 0;
+ tbl->max_ids = 0;
+ tbl->ids = NULL;
+ }
+
+ if (!super->id_count || super->id_table_start >= super->bytes_used) {
+ fputs("ID table missing from file system\n", stderr);
+ return -1;
+ }
+
+ 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;
+ }
+
+ tbl->num_ids = super->id_count;
+ tbl->max_ids = super->id_count;
+ tbl->ids = sqfs_read_table(fd, cmp, tbl->num_ids * sizeof(uint32_t),
+ super->id_table_start, lower_limit,
+ upper_limit);
+ if (tbl->ids == NULL)
+ return -1;
+
+ for (i = 0; i < tbl->num_ids; ++i)
+ tbl->ids[i] = le32toh(tbl->ids[i]);
+
+ return 0;
+}
+
+int id_table_write(id_table_t *tbl, int outfd, sqfs_super_t *super,
+ compressor_t *cmp)
+{
+ uint64_t start;
+ size_t i;
+ int ret;
+
+ for (i = 0; i < tbl->num_ids; ++i)
+ tbl->ids[i] = htole32(tbl->ids[i]);
+
+ super->id_count = tbl->num_ids;
+
+ ret = sqfs_write_table(outfd, super, cmp, tbl->ids,
+ sizeof(tbl->ids[0]) * tbl->num_ids, &start);
+
+ super->id_table_start = start;
+
+ for (i = 0; i < tbl->num_ids; ++i)
+ tbl->ids[i] = le32toh(tbl->ids[i]);
+
+ return ret;
+}