aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/id_table.h3
-rw-r--r--lib/Makemodule.am3
-rw-r--r--lib/sqfs/id_table.c21
-rw-r--r--lib/sqfs/id_table_read.c96
-rw-r--r--lib/sqfs/id_table_write.c23
-rw-r--r--unpack/unsquashfs.c12
6 files changed, 135 insertions, 23 deletions
diff --git a/include/id_table.h b/include/id_table.h
index c49923e..600eb64 100644
--- a/include/id_table.h
+++ b/include/id_table.h
@@ -22,4 +22,7 @@ int id_table_id_to_index(id_table_t *tbl, uint32_t id, uint16_t *out);
int id_table_write(id_table_t *tbl, int outfd, sqfs_super_t *super,
compressor_t *cmp);
+int id_table_read(id_table_t *tbl, int fd, sqfs_super_t *super,
+ compressor_t *cmp);
+
#endif /* ID_TABLE_H */
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index 5cadf58..08b53e1 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -12,7 +12,8 @@ libsquashfs_a_SOURCES += lib/sqfs/meta_writer.c lib/sqfs/super.c
libsquashfs_a_SOURCES += lib/sqfs/id_table.c include/id_table.h
libsquashfs_a_SOURCES += lib/sqfs/table.c include/table.h
libsquashfs_a_SOURCES += lib/sqfs/read_super.c lib/sqfs/meta_reader.c
-libsquashfs_a_SOURCES += include/meta_reader.h
+libsquashfs_a_SOURCES += include/meta_reader.h lib/sqfs/id_table_write.c
+libsquashfs_a_SOURCES += lib/sqfs/id_table_read.c
libutil_a_SOURCES = lib/util/canonicalize_name.c lib/util/write_retry.c
libutil_a_SOURCES += lib/util/read_retry.c include/util.h
diff --git a/lib/sqfs/id_table.c b/lib/sqfs/id_table.c
index 4cc12c6..cd31360 100644
--- a/lib/sqfs/id_table.c
+++ b/lib/sqfs/id_table.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
#include "id_table.h"
-#include "table.h"
#include <stdlib.h>
#include <string.h>
@@ -51,23 +50,3 @@ 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_write(id_table_t *tbl, int outfd, sqfs_super_t *super,
- compressor_t *cmp)
-{
- 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, tbl->ids, sizeof(tbl->ids[0]),
- tbl->num_ids, &super->id_table_start, cmp);
-
- for (i = 0; i < tbl->num_ids; ++i)
- tbl->ids[i] = le32toh(tbl->ids[i]);
-
- return ret;
-}
diff --git a/lib/sqfs/id_table_read.c b/lib/sqfs/id_table_read.c
new file mode 100644
index 0000000..b1305ff
--- /dev/null
+++ b/lib/sqfs/id_table_read.c
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+#include "meta_reader.h"
+#include "id_table.h"
+#include "table.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;
+ ssize_t ret;
+
+ 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;
+ }
+
+ tbl->ids = malloc(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;
+
+ if (lseek(fd, super->id_table_start, SEEK_SET) == (off_t)-1)
+ goto fail_seek;
+
+ block_count = super->id_count / 2048;
+ if (super->id_count % 2048)
+ ++block_count;
+
+ ret = read_retry(fd, blocks, sizeof(blocks[0]) * block_count);
+ if (ret < 0)
+ goto fail_rd;
+
+ if ((size_t)ret < sizeof(blocks[0]) * block_count)
+ goto fail_trunc;
+
+ for (i = 0; i < block_count; ++i)
+ blocks[i] = le64toh(blocks[i]);
+
+ m = meta_reader_create(fd, cmp);
+ if (m == NULL)
+ 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;
+fail_trunc:
+ fputs("reading ID table: unexpected end of file\n", stderr);
+ return -1;
+fail_rd:
+ perror("reading ID table");
+ return -1;
+fail_seek:
+ perror("seeking to ID table");
+ return -1;
+}
diff --git a/lib/sqfs/id_table_write.c b/lib/sqfs/id_table_write.c
new file mode 100644
index 0000000..490c2af
--- /dev/null
+++ b/lib/sqfs/id_table_write.c
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+#include "id_table.h"
+#include "table.h"
+
+int id_table_write(id_table_t *tbl, int outfd, sqfs_super_t *super,
+ compressor_t *cmp)
+{
+ 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, tbl->ids, sizeof(tbl->ids[0]),
+ tbl->num_ids, &super->id_table_start, cmp);
+
+ for (i = 0; i < tbl->num_ids; ++i)
+ tbl->ids[i] = le32toh(tbl->ids[i]);
+
+ return ret;
+}
diff --git a/unpack/unsquashfs.c b/unpack/unsquashfs.c
index 4606366..f5c3a43 100644
--- a/unpack/unsquashfs.c
+++ b/unpack/unsquashfs.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
#include "squashfs.h"
#include "compress.h"
+#include "id_table.h"
#include <stdlib.h>
#include <unistd.h>
@@ -14,6 +15,7 @@ int main(int argc, char **argv)
int fd, status = EXIT_FAILURE;
sqfs_super_t super;
compressor_t *cmp;
+ id_table_t idtbl;
if (argc != 2) {
fprintf(stderr, "Usage: %s <filename>\n", __progname);
@@ -56,8 +58,16 @@ int main(int argc, char **argv)
if (cmp == NULL)
goto out;
- status = EXIT_SUCCESS;
+ if (id_table_init(&idtbl))
+ goto out_cmp;
+
+ if (id_table_read(&idtbl, fd, &super, cmp))
+ goto out_idtbl;
+ status = EXIT_SUCCESS;
+out_idtbl:
+ id_table_cleanup(&idtbl);
+out_cmp:
cmp->destroy(cmp);
out:
close(fd);