summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makemodule.am1
-rw-r--r--lib/sqfs/read_super.c84
2 files changed, 85 insertions, 0 deletions
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index c2d7dab..026e3f1 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -11,6 +11,7 @@ libsquashfs_a_SOURCES = include/meta_writer.h include/squashfs.h
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
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/read_super.c b/lib/sqfs/read_super.c
new file mode 100644
index 0000000..22dd822
--- /dev/null
+++ b/lib/sqfs/read_super.c
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+#include "squashfs.h"
+#include "util.h"
+
+#include <endian.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int sqfs_super_read(sqfs_super_t *super, int fd)
+{
+ sqfs_super_t temp;
+ size_t block_size;
+ ssize_t ret;
+ int i;
+
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1)
+ goto fail_seek;
+
+ ret = read_retry(fd, &temp, sizeof(temp));
+
+ if (ret < 0) {
+ perror("reading super block");
+ return -1;
+ }
+
+ if ((size_t)ret < sizeof(temp)) {
+ fputs("reading super block: unexpected end of file\n", stderr);
+ return -1;
+ }
+
+ temp.magic = le32toh(temp.magic);
+ temp.inode_count = le32toh(temp.inode_count);
+ temp.modification_time = le32toh(temp.modification_time);
+ temp.block_size = le32toh(temp.block_size);
+ temp.fragment_entry_count = le32toh(temp.fragment_entry_count);
+ temp.compression_id = le16toh(temp.compression_id);
+ temp.block_log = le16toh(temp.block_log);
+ temp.flags = le16toh(temp.flags);
+ temp.id_count = le16toh(temp.id_count);
+ temp.version_major = le16toh(temp.version_major);
+ temp.version_minor = le16toh(temp.version_minor);
+ temp.root_inode_ref = le64toh(temp.root_inode_ref);
+ temp.bytes_used = le64toh(temp.bytes_used);
+ temp.id_table_start = le64toh(temp.id_table_start);
+ temp.xattr_id_table_start = le64toh(temp.xattr_id_table_start);
+ temp.inode_table_start = le64toh(temp.inode_table_start);
+ temp.directory_table_start = le64toh(temp.directory_table_start);
+ temp.fragment_table_start = le64toh(temp.fragment_table_start);
+ temp.export_table_start = le64toh(temp.export_table_start);
+
+ if (temp.magic != SQFS_MAGIC) {
+ fputs("Magic number missing. Not a squashfs image.\n", stderr);
+ return -1;
+ }
+
+ if ((temp.block_size - 1) & temp.block_size) {
+ fputs("Block size in image is not a power of 2!\n", stderr);
+ return -1;
+ }
+
+ block_size = 1;
+
+ for (i = 0; i < temp.block_log; ++i)
+ block_size <<= 1;
+
+ if (temp.block_size != block_size) {
+ fputs("Mismatch between block size and block log\n", stderr);
+ fputs("Filesystem probably currupted.\n", stderr);
+ return -1;
+ }
+
+ if (temp.compression_id < SQFS_COMP_MIN ||
+ temp.compression_id > SQFS_COMP_MAX) {
+ fputs("Image uses an unsupported compressor\n", stderr);
+ return -1;
+ }
+
+ memcpy(super, &temp, sizeof(temp));
+ return 0;
+fail_seek:
+ perror("squashfs writing super block: seek on output file");
+ return -1;
+}