summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-25 20:09:20 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-25 20:13:11 +0200
commit37bf7752c31d8fda8faad0cf5f89328215305c60 (patch)
tree2d005da012ae20c62f93b47b713c42aaa46fe589
parentf49fe3bbf0d52e2afcc1ace8c1f48dee9349d4f8 (diff)
Add generic read_table function similar to write_table
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/highlevel.h3
-rw-r--r--lib/Makemodule.am1
-rw-r--r--lib/sqfs/frag_reader.c81
-rw-r--r--lib/sqfs/id_table_read.c52
-rw-r--r--lib/sqfs/read_table.c79
5 files changed, 104 insertions, 112 deletions
diff --git a/include/highlevel.h b/include/highlevel.h
index 16db1cf..cef6190 100644
--- a/include/highlevel.h
+++ b/include/highlevel.h
@@ -34,6 +34,9 @@ enum RDTREE_FLAGS {
int sqfs_write_table(int outfd, sqfs_super_t *super, compressor_t *cmp,
const void *data, size_t table_size, uint64_t *start);
+void *sqfs_read_table(int fd, compressor_t *cmp, size_t table_size,
+ uint64_t location);
+
/*
High level helper function to serialize an entire file system tree to
a squashfs inode table and directory table.
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index 2332a73..c6674c0 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -36,6 +36,7 @@ libsquashfs_a_SOURCES += lib/sqfs/data_writer.c lib/sqfs/write_xattr.c
libsquashfs_a_SOURCES += include/data_writer.h include/frag_reader.h
libsquashfs_a_SOURCES += include/data_reader.h lib/sqfs/data_reader.c
libsquashfs_a_SOURCES += lib/sqfs/write_export_table.c
+libsquashfs_a_SOURCES += lib/sqfs/read_table.c
libutil_a_SOURCES = lib/util/canonicalize_name.c lib/util/write_data.c
libutil_a_SOURCES += lib/util/read_data.c include/util.h
diff --git a/lib/sqfs/frag_reader.c b/lib/sqfs/frag_reader.c
index 51b40e9..2adfe01 100644
--- a/lib/sqfs/frag_reader.c
+++ b/lib/sqfs/frag_reader.c
@@ -1,11 +1,10 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
#include "config.h"
-#include "meta_reader.h"
#include "frag_reader.h"
+#include "highlevel.h"
#include "util.h"
-#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -66,83 +65,35 @@ static int precache_block(frag_reader_t *f, size_t i)
frag_reader_t *frag_reader_create(sqfs_super_t *super, int fd,
compressor_t *cmp)
{
- size_t i, blockcount, j, diff, count;
sqfs_fragment_t *tbl = NULL;
- uint64_t *locations = NULL;
- meta_reader_t *m = NULL;
frag_reader_t *f = NULL;
+ size_t i;
- count = super->fragment_entry_count;
- blockcount = count / (SQFS_META_BLOCK_SIZE / sizeof(tbl[0]));
-
- if (count % (SQFS_META_BLOCK_SIZE / sizeof(tbl[0])))
- ++blockcount;
-
- /* pre allocate all the stuff */
f = calloc(1, sizeof(*f) + super->block_size * 2);
- if (f == NULL)
- goto fail_rd;
-
- tbl = calloc(count, sizeof(tbl[0]));
- if (tbl == NULL)
- goto fail_rd;
-
- locations = malloc(blockcount * sizeof(locations[0]));
- if (locations == NULL)
- goto fail_rd;
-
- /* read the meta block offset table */
- if (read_data_at("reading fragment table", super->fragment_table_start,
- fd, locations, blockcount * sizeof(locations[0]))) {
- goto fail;
+ if (f == NULL) {
+ perror("creating fragment table");
+ return NULL;
}
- for (i = 0; i < blockcount; ++i)
- locations[i] = le64toh(locations[i]);
-
- /* read the meta blocks */
- m = meta_reader_create(fd, cmp);
- if (m == NULL)
- goto fail;
-
- for (i = 0, j = 0; i < blockcount && j < count; ++i, j += diff) {
- if (meta_reader_seek(m, locations[i], 0))
- goto fail;
-
- diff = SQFS_META_BLOCK_SIZE / sizeof(tbl[0]);
- if (diff > (count - j))
- diff = count - j;
+ f->block_size = super->block_size;
+ f->num_fragments = super->fragment_entry_count;
+ f->current_index = f->num_fragments;
+ f->cmp = cmp;
+ f->fd = fd;
- if (meta_reader_read(m, tbl + j, diff * sizeof(tbl[0])))
- goto fail;
+ f->tbl = sqfs_read_table(fd, cmp, sizeof(tbl[0]) * f->num_fragments,
+ super->fragment_table_start);
+ if (f->tbl == NULL) {
+ free(f);
+ return NULL;
}
- for (i = 0; i < count; ++i) {
+ for (i = 0; i < f->num_fragments; ++i) {
tbl[i].start_offset = le64toh(tbl[i].start_offset);
tbl[i].size = le32toh(tbl[i].size);
}
- /* cleanup and ship it */
- meta_reader_destroy(m);
- free(locations);
-
- f->tbl = tbl;
- f->num_fragments = count;
- f->cmp = cmp;
- f->fd = fd;
- f->block_size = super->block_size;
- f->current_index = count;
return f;
-fail_rd:
- perror("reading fragment table");
- goto fail;
-fail:
- if (m != NULL)
- meta_reader_destroy(m);
- free(tbl);
- free(locations);
- free(f);
- return NULL;
}
void frag_reader_destroy(frag_reader_t *f)
diff --git a/lib/sqfs/id_table_read.c b/lib/sqfs/id_table_read.c
index 1e92f75..bed0cf4 100644
--- a/lib/sqfs/id_table_read.c
+++ b/lib/sqfs/id_table_read.c
@@ -1,21 +1,16 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
#include "config.h"
-#include "meta_reader.h"
#include "highlevel.h"
#include "util.h"
#include <stdlib.h>
-#include <unistd.h>
#include <stdio.h>
int id_table_read(id_table_t *tbl, int fd, sqfs_super_t *super,
compressor_t *cmp)
{
- size_t i, block_count, count, diff;
- uint64_t blocks[32];
- meta_reader_t *m;
- uint32_t *ptr;
+ size_t i;
if (tbl->ids != NULL) {
free(tbl->ids);
@@ -29,54 +24,17 @@ int id_table_read(id_table_t *tbl, int fd, sqfs_super_t *super,
return -1;
}
- tbl->ids = calloc(super->id_count, sizeof(uint32_t));
- if (tbl->ids == NULL) {
- perror("reading ID table");
- return -1;
- }
-
tbl->num_ids = super->id_count;
tbl->max_ids = super->id_count;
-
- block_count = super->id_count / 2048;
- if (super->id_count % 2048)
- ++block_count;
-
- if (read_data_at("reading ID table", super->id_table_start, fd,
- blocks, sizeof(blocks[0]) * block_count)) {
- return -1;
- }
-
- for (i = 0; i < block_count; ++i)
- blocks[i] = le64toh(blocks[i]);
-
- m = meta_reader_create(fd, cmp);
- if (m == NULL)
+ tbl->ids = sqfs_read_table(fd, cmp, tbl->num_ids * sizeof(uint32_t),
+ super->id_table_start);
+ if (tbl->ids == NULL) {
+ free(tbl);
return -1;
-
- count = super->id_count;
- ptr = tbl->ids;
-
- for (i = 0; i < block_count && count > 0; ++i) {
- diff = count < 2048 ? count : 2048;
-
- if (meta_reader_seek(m, blocks[i], 0))
- goto fail_meta;
-
- if (meta_reader_read(m, ptr, diff * sizeof(tbl->ids[0])))
- goto fail_meta;
-
- count -= diff;
- ptr += diff;
}
- meta_reader_destroy(m);
-
for (i = 0; i < tbl->num_ids; ++i)
tbl->ids[i] = le32toh(tbl->ids[i]);
return 0;
-fail_meta:
- meta_reader_destroy(m);
- return -1;
}
diff --git a/lib/sqfs/read_table.c b/lib/sqfs/read_table.c
new file mode 100644
index 0000000..8fc8ebf
--- /dev/null
+++ b/lib/sqfs/read_table.c
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+#include "config.h"
+
+#include "meta_reader.h"
+#include "highlevel.h"
+#include "util.h"
+
+#include <endian.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void *sqfs_read_table(int fd, compressor_t *cmp, size_t table_size,
+ uint64_t location)
+{
+ size_t diff, block_count, list_size, blk_idx = 0;
+ uint64_t start, *locations;
+ meta_reader_t *m;
+ void *data, *ptr;
+
+ data = malloc(table_size);
+ if (data == NULL) {
+ perror("reading table");
+ return NULL;
+ }
+
+ /* restore list from image */
+ block_count = table_size / SQFS_META_BLOCK_SIZE;
+
+ if ((table_size % SQFS_META_BLOCK_SIZE) != 0)
+ ++block_count;
+
+ list_size = sizeof(uint64_t) * block_count;
+ locations = malloc(list_size);
+
+ if (locations == NULL) {
+ perror("allocation table location list");
+ goto fail_data;
+ }
+
+ if (read_data_at("reading table locations", location,
+ fd, locations, list_size)) {
+ goto fail_idx;
+ }
+
+ /* Read the actual data */
+ m = meta_reader_create(fd, cmp);
+ if (m == NULL)
+ goto fail_idx;
+
+ ptr = data;
+
+ while (table_size > 0) {
+ start = le64toh(locations[blk_idx++]);
+
+ if (meta_reader_seek(m, start, 0))
+ goto fail;
+
+ diff = SQFS_META_BLOCK_SIZE;
+ if (diff > table_size)
+ diff = table_size;
+
+ if (meta_reader_read(m, ptr, diff))
+ goto fail;
+
+ ptr = (char *)ptr + diff;
+ table_size -= diff;
+ }
+
+ meta_reader_destroy(m);
+ free(locations);
+ return data;
+fail:
+ meta_reader_destroy(m);
+fail_idx:
+ free(locations);
+fail_data:
+ free(data);
+ return NULL;
+}