diff options
-rw-r--r-- | include/highlevel.h | 19 | ||||
-rw-r--r-- | lib/Makemodule.am | 1 | ||||
-rw-r--r-- | lib/sqfs/sqfs_reader.c | 72 | ||||
-rw-r--r-- | tar/sqfs2tar.c | 68 | ||||
-rw-r--r-- | unpack/rdsquashfs.c | 66 |
5 files changed, 118 insertions, 108 deletions
diff --git a/include/highlevel.h b/include/highlevel.h index e3afbd7..f8c5bfb 100644 --- a/include/highlevel.h +++ b/include/highlevel.h @@ -9,6 +9,7 @@ #include "config.h" +#include "data_reader.h" #include "squashfs.h" #include "compress.h" #include "id_table.h" @@ -17,6 +18,14 @@ #include <stdint.h> #include <stddef.h> +typedef struct { + compressor_t *cmp; + data_reader_t *data; + sqfs_super_t super; + fstree_t fs; + int sqfsfd; +} sqfs_reader_t; + enum RDTREE_FLAGS { RDTREE_NO_DEVICES = 0x01, RDTREE_NO_SOCKETS = 0x02, @@ -96,4 +105,14 @@ int write_export_table(int outfd, fstree_t *fs, sqfs_super_t *super, /* Print out fancy statistics for squashfs packing tools */ void sqfs_print_statistics(fstree_t *fs, sqfs_super_t *super); +/* Open a squashfs file, extract all the information we may need and + construct datastructures we need to access its contents. + Returns 0 on success. Prints error messages to stderr on failure. +*/ +int sqfs_reader_open(sqfs_reader_t *rd, const char *filename, + int rdtree_flags); + +/* Cleanup after a successfull sqfs_reader_open */ +void sqfs_reader_close(sqfs_reader_t *rd); + #endif /* HIGHLEVEL_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index c3451f4..82c910c 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -39,6 +39,7 @@ libsquashfs_a_SOURCES += include/data_writer.h include/xattr_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 lib/sqfs/statistics.c +libsquashfs_a_SOURCES += lib/sqfs/sqfs_reader.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/sqfs_reader.c b/lib/sqfs/sqfs_reader.c new file mode 100644 index 0000000..85cf97a --- /dev/null +++ b/lib/sqfs/sqfs_reader.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * sqfs_reader.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "highlevel.h" + +#include <string.h> +#include <unistd.h> +#include <fcntl.h> + +int sqfs_reader_open(sqfs_reader_t *rd, const char *filename, int rdtree_flags) +{ + memset(rd, 0, sizeof(*rd)); + + rd->sqfsfd = open(filename, O_RDONLY); + if (rd->sqfsfd < 0) { + perror(filename); + return -1; + } + + if (sqfs_super_read(&rd->super, rd->sqfsfd)) + goto fail_fd; + + if (!compressor_exists(rd->super.compression_id)) { + fprintf(stderr, "%s: unknown compressor used.\n", filename); + goto fail_fd; + } + + rd->cmp = compressor_create(rd->super.compression_id, false, + rd->super.block_size, NULL); + if (rd->cmp == NULL) + goto fail_fd; + + if (rd->super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { + if (rd->cmp->read_options(rd->cmp, rd->sqfsfd)) + goto fail_cmp; + } + + if (deserialize_fstree(&rd->fs, &rd->super, rd->cmp, rd->sqfsfd, + rdtree_flags)) { + goto fail_cmp; + } + + fstree_gen_file_list(&rd->fs); + + rd->data = data_reader_create(rd->sqfsfd, &rd->super, rd->cmp); + if (rd->data == NULL) + goto fail_fs; + + return 0; +fail_fs: + fstree_cleanup(&rd->fs); +fail_cmp: + rd->cmp->destroy(rd->cmp); +fail_fd: + close(rd->sqfsfd); + memset(rd, 0, sizeof(*rd)); + return -1; +} + +void sqfs_reader_close(sqfs_reader_t *rd) +{ + data_reader_destroy(rd->data); + fstree_cleanup(&rd->fs); + rd->cmp->destroy(rd->cmp); + close(rd->sqfsfd); + memset(rd, 0, sizeof(*rd)); +} diff --git a/tar/sqfs2tar.c b/tar/sqfs2tar.c index a49efda..59e9703 100644 --- a/tar/sqfs2tar.c +++ b/tar/sqfs2tar.c @@ -302,89 +302,51 @@ skip_hdr: int main(int argc, char **argv) { - int sqfsfd, rdtree_flags = 0; - data_reader_t *data = NULL; - int status = EXIT_FAILURE; - sqfs_super_t super; - compressor_t *cmp; + int rdtree_flags = 0, status = EXIT_FAILURE; + sqfs_reader_t sqfs; tree_node_t *root; - fstree_t fs; size_t i; process_args(argc, argv); - sqfsfd = open(filename, O_RDONLY); - if (sqfsfd < 0) { - perror(filename); - return EXIT_FAILURE; - } - - if (sqfs_super_read(&super, sqfsfd)) - goto out_fd; - - if (!compressor_exists(super.compression_id)) { - fputs("Image uses a compressor that has not been built in\n", - stderr); - goto out_fd; - } - - cmp = compressor_create(super.compression_id, false, - super.block_size, NULL); - if (cmp == NULL) - goto out_fd; - - if (super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { - if (cmp->read_options(cmp, sqfsfd)) - goto out_cmp; - } - if (!no_xattr) rdtree_flags |= RDTREE_READ_XATTR; - if (deserialize_fstree(&fs, &super, cmp, sqfsfd, rdtree_flags)) - goto out_cmp; - - data = data_reader_create(sqfsfd, &super, cmp); - if (data == NULL) - goto out_fs; + if (sqfs_reader_open(&sqfs, filename, rdtree_flags)) + goto out_dirs; for (i = 0; i < num_subdirs; ++i) { - root = fstree_node_from_path(&fs, subdirs[i]); + root = fstree_node_from_path(&sqfs.fs, subdirs[i]); if (root == NULL) { perror(subdirs[i]); - goto out_data; + goto out; } if (!S_ISDIR(root->mode)) { fprintf(stderr, "%s is not a directory\n", subdirs[i]); - goto out_data; + goto out; } current_subdir = subdirs[i]; - if (write_tree_dfs(&fs, root, data)) - goto out_data; + if (write_tree_dfs(&sqfs.fs, root, sqfs.data)) + goto out; } current_subdir = NULL; if (num_subdirs == 0) { - if (write_tree_dfs(&fs, fs.root, data)) - goto out_data; + if (write_tree_dfs(&sqfs.fs, sqfs.fs.root, sqfs.data)) + goto out; } if (terminate_archive()) - goto out_data; + goto out; status = EXIT_SUCCESS; -out_data: - data_reader_destroy(data); -out_fs: - fstree_cleanup(&fs); -out_cmp: - cmp->destroy(cmp); -out_fd: - close(sqfsfd); +out: + sqfs_reader_close(&sqfs); +out_dirs: for (i = 0; i < num_subdirs; ++i) free(subdirs[i]); free(subdirs); diff --git a/unpack/rdsquashfs.c b/unpack/rdsquashfs.c index dc43fcd..4fb3a78 100644 --- a/unpack/rdsquashfs.c +++ b/unpack/rdsquashfs.c @@ -24,54 +24,23 @@ static void dump_xattrs(fstree_t *fs, tree_xattr_t *xattr) int main(int argc, char **argv) { int status = EXIT_FAILURE; - data_reader_t *data = NULL; - sqfs_super_t super; - compressor_t *cmp; + sqfs_reader_t sqfs; tree_node_t *n; options_t opt; - fstree_t fs; - int sqfsfd; process_command_line(&opt, argc, argv); - sqfsfd = open(opt.image_name, O_RDONLY); - if (sqfsfd < 0) { - perror(opt.image_name); + if (sqfs_reader_open(&sqfs, opt.image_name, opt.rdtree_flags)) goto out_cmd; - } - - if (sqfs_super_read(&super, sqfsfd)) - goto out_fd; - - if (!compressor_exists(super.compression_id)) { - fputs("Image uses a compressor that has not been built in\n", - stderr); - goto out_fd; - } - - cmp = compressor_create(super.compression_id, false, - super.block_size, NULL); - if (cmp == NULL) - goto out_fd; - - if (super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { - if (cmp->read_options(cmp, sqfsfd)) - goto out_cmp; - } - - if (deserialize_fstree(&fs, &super, cmp, sqfsfd, opt.rdtree_flags)) - goto out_cmp; - - fstree_gen_file_list(&fs); if (opt.cmdpath != NULL) { - n = fstree_node_from_path(&fs, opt.cmdpath); + n = fstree_node_from_path(&sqfs.fs, opt.cmdpath); if (n == NULL) { perror(opt.cmdpath); goto out_fs; } } else { - n = fs.root; + n = sqfs.fs.root; } switch (opt.op) { @@ -85,11 +54,7 @@ int main(int argc, char **argv) goto out_fs; } - data = data_reader_create(sqfsfd, &super, cmp); - if (data == NULL) - goto out_fs; - - if (data_reader_dump_file(data, n->data.file, + if (data_reader_dump_file(sqfs.data, n->data.file, STDOUT_FILENO, false)) goto out_fs; break; @@ -105,38 +70,29 @@ int main(int argc, char **argv) if (restore_fstree(n, opt.flags)) goto out_fs; - data = data_reader_create(sqfsfd, &super, cmp); - if (data == NULL) - goto out_fs; - - if (fill_unpacked_files(&fs, data, opt.flags, opt.num_jobs)) + if (fill_unpacked_files(&sqfs.fs, sqfs.data, + opt.flags, opt.num_jobs)) goto out_fs; - if (update_tree_attribs(&fs, n, opt.flags)) + if (update_tree_attribs(&sqfs.fs, n, opt.flags)) goto out_fs; if (opt.unpack_root != NULL && popd() != 0) goto out_fs; break; case OP_DESCRIBE: - if (describe_tree(fs.root, opt.unpack_root)) + if (describe_tree(sqfs.fs.root, opt.unpack_root)) goto out_fs; break; case OP_RDATTR: if (n->xattr != NULL) - dump_xattrs(&fs, n->xattr); + dump_xattrs(&sqfs.fs, n->xattr); break; } status = EXIT_SUCCESS; out_fs: - if (data != NULL) - data_reader_destroy(data); - fstree_cleanup(&fs); -out_cmp: - cmp->destroy(cmp); -out_fd: - close(sqfsfd); + sqfs_reader_close(&sqfs); out_cmd: free(opt.cmdpath); return status; |