From 4da96898487f0f4aca1dfc7afc355aa90065308a Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Wed, 1 May 2019 13:35:33 +0200 Subject: Add unsquashfs stub Signed-off-by: David Oberhollenzer --- .gitignore | 1 + Makefile.am | 1 + include/squashfs.h | 2 ++ lib/Makemodule.am | 1 + lib/sqfs/read_super.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ unpack/Makemodule.am | 12 ++++++++ unpack/unsquashfs.c | 65 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 166 insertions(+) create mode 100644 lib/sqfs/read_super.c create mode 100644 unpack/Makemodule.am create mode 100644 unpack/unsquashfs.c diff --git a/.gitignore b/.gitignore index d10a7fe..944a414 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ config.h *.a *~ mksquashfs +unsquashfs diff --git a/Makefile.am b/Makefile.am index 1b8284b..7fc95c3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,3 +10,4 @@ EXTRA_DIST = autogen.sh LICENSE include lib/Makemodule.am include mkfs/Makemodule.am +include unpack/Makemodule.am diff --git a/include/squashfs.h b/include/squashfs.h index 30c7d3d..a690aad 100644 --- a/include/squashfs.h +++ b/include/squashfs.h @@ -184,4 +184,6 @@ int sqfs_super_init(sqfs_super_t *super, size_t block_size, uint32_t mtime, int sqfs_super_write(sqfs_super_t *super, int fd); +int sqfs_super_read(sqfs_super_t *super, int fd); + #endif /* SQUASHFS_H */ 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 +#include +#include +#include + +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; +} diff --git a/unpack/Makemodule.am b/unpack/Makemodule.am new file mode 100644 index 0000000..190803e --- /dev/null +++ b/unpack/Makemodule.am @@ -0,0 +1,12 @@ +unsquashfs_SOURCES = unpack/unsquashfs.c +unsquashfs_LDADD = libsquashfs.a libfstree.a libcompress.a libutil.a + +if WITH_LZMA +unsquashfs_LDADD += $(XZ_LIBS) +endif + +if WITH_ZLIB +unsquashfs_LDADD += $(ZLIB_LIBS) +endif + +bin_PROGRAMS += unsquashfs diff --git a/unpack/unsquashfs.c b/unpack/unsquashfs.c new file mode 100644 index 0000000..4606366 --- /dev/null +++ b/unpack/unsquashfs.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "squashfs.h" +#include "compress.h" + +#include +#include +#include +#include + +extern const char *__progname; + +int main(int argc, char **argv) +{ + int fd, status = EXIT_FAILURE; + sqfs_super_t super; + compressor_t *cmp; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", __progname); + return EXIT_FAILURE; + } + + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + perror(argv[1]); + return EXIT_FAILURE; + } + + if (sqfs_super_read(&super, fd)) + goto out; + + if ((super.version_major != SQFS_VERSION_MAJOR) || + (super.version_minor != SQFS_VERSION_MINOR)) { + fprintf(stderr, + "The image uses squashfs version %d.%d\n" + "We currently only supports version %d.%d (sorry).\n", + super.version_major, super.version_minor, + SQFS_VERSION_MAJOR, SQFS_VERSION_MINOR); + goto out; + } + + if (super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { + fputs("Image has been built with compressor options.\n" + "This is not yet supported.\n", + stderr); + goto out; + } + + if (!compressor_exists(super.compression_id)) { + fputs("Image uses a compressor that has not been built in\n", + stderr); + goto out; + } + + cmp = compressor_create(super.compression_id, false, super.block_size); + if (cmp == NULL) + goto out; + + status = EXIT_SUCCESS; + + cmp->destroy(cmp); +out: + close(fd); + return status; +} -- cgit v1.2.3