From 37bf7752c31d8fda8faad0cf5f89328215305c60 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 25 Jul 2019 20:09:20 +0200 Subject: Add generic read_table function similar to write_table Signed-off-by: David Oberhollenzer --- include/highlevel.h | 3 ++ lib/Makemodule.am | 1 + lib/sqfs/frag_reader.c | 81 ++++++++++-------------------------------------- lib/sqfs/id_table_read.c | 52 +++---------------------------- lib/sqfs/read_table.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 112 deletions(-) create mode 100644 lib/sqfs/read_table.c 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 #include #include #include @@ -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 -#include #include 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 +#include +#include + +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; +} -- cgit v1.2.3