From 5b1a81160a6d0e63ab1360e8777009b913464d89 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 8 Jun 2023 13:22:13 +0200 Subject: Move tar compressor auto wrapping code from tar2sqfs into libtar Signed-off-by: David Oberhollenzer --- bin/tar2sqfs/src/process_tarball.c | 18 +++------- bin/tar2sqfs/src/tar2sqfs.c | 71 ++++++-------------------------------- bin/tar2sqfs/src/tar2sqfs.h | 3 +- lib/tar/Makemodule.am | 12 +++++-- lib/tar/src/iterator.c | 66 +++++++++++++++++++++++++++++++++-- 5 files changed, 88 insertions(+), 82 deletions(-) diff --git a/bin/tar2sqfs/src/process_tarball.c b/bin/tar2sqfs/src/process_tarball.c index 9ad7d9a..91572ec 100644 --- a/bin/tar2sqfs/src/process_tarball.c +++ b/bin/tar2sqfs/src/process_tarball.c @@ -148,16 +148,10 @@ static int set_root_attribs(sqfs_writer_t *sqfs, dir_iterator_t *it, return 0; } -int process_tarball(istream_t *input_file, sqfs_writer_t *sqfs) +int process_tarball(dir_iterator_t *it, sqfs_writer_t *sqfs) { - dir_iterator_t *it = tar_open_stream(input_file); size_t rootlen = root_becomes == NULL ? 0 : strlen(root_becomes); - if (it == NULL) { - fputs("Creating tar stream: out-of-memory\n", stderr); - return -1; - } - for (;;) { bool skip = false, is_root = false, is_prefixed = true; dir_entry_t *ent = NULL; @@ -168,7 +162,7 @@ int process_tarball(istream_t *input_file, sqfs_writer_t *sqfs) if (ret > 0) break; if (ret < 0) - goto fail; + return -1; if (ent->mtime < 0) ent->mtime = 0; @@ -181,7 +175,7 @@ int process_tarball(istream_t *input_file, sqfs_writer_t *sqfs) if (ret != 0) { sqfs_perror(ent->name, "read link", ret); free(ent); - goto fail; + return -1; } } @@ -235,12 +229,8 @@ int process_tarball(istream_t *input_file, sqfs_writer_t *sqfs) free(ent); free(link); if (ret) - goto fail; + return -1; } - sqfs_drop(it); return 0; -fail: - sqfs_drop(it); - return -1; } diff --git a/bin/tar2sqfs/src/tar2sqfs.c b/bin/tar2sqfs/src/tar2sqfs.c index 1145675..b09f920 100644 --- a/bin/tar2sqfs/src/tar2sqfs.c +++ b/bin/tar2sqfs/src/tar2sqfs.c @@ -6,65 +6,11 @@ */ #include "tar2sqfs.h" -static int tar_probe(const sqfs_u8 *data, size_t size) -{ - size_t i, offset; - - if (size >= TAR_RECORD_SIZE) { - for (i = 0; i < TAR_RECORD_SIZE; ++i) { - if (data[i] != 0x00) - break; - } - - if (i == TAR_RECORD_SIZE) { - data += TAR_RECORD_SIZE; - size -= TAR_RECORD_SIZE; - } - } - - offset = offsetof(tar_header_t, magic); - - if (offset + 5 <= size) { - if (memcmp(data + offset, "ustar", 5) == 0) - return 1; - } - - return 0; -} - -static istream_t *magic_autowrap(istream_t *strm) -{ - xfrm_stream_t *xfrm = NULL; - istream_t *wrapper = NULL; - int ret; - - ret = istream_precache(strm); - if (ret != 0) - goto out; - - ret = tar_probe(strm->buffer, strm->buffer_used); - if (ret > 0) - return strm; - - ret = xfrm_compressor_id_from_magic(strm->buffer, strm->buffer_used); - if (ret <= 0) - return strm; - - xfrm = decompressor_stream_create(ret); - if (xfrm == NULL) - goto out; - - wrapper = istream_xfrm_create(strm, xfrm); -out: - sqfs_drop(strm); - sqfs_drop(xfrm); - return wrapper; -} - int main(int argc, char **argv) { int status = EXIT_FAILURE; istream_t *input_file = NULL; + dir_iterator_t *tar = NULL; sqfs_writer_t sqfs; process_args(argc, argv); @@ -73,15 +19,18 @@ int main(int argc, char **argv) if (input_file == NULL) return EXIT_FAILURE; - input_file = magic_autowrap(input_file); - if (input_file == NULL) + tar = tar_open_stream(input_file); + sqfs_drop(input_file); + if (tar == NULL) { + fputs("Creating tar stream: out-of-memory\n", stderr); return EXIT_FAILURE; + } memset(&sqfs, 0, sizeof(sqfs)); if (sqfs_writer_init(&sqfs, &cfg)) - goto out_if; + goto out_it; - if (process_tarball(input_file, &sqfs)) + if (process_tarball(tar, &sqfs)) goto out; if (fstree_post_process(&sqfs.fs)) @@ -93,7 +42,7 @@ int main(int argc, char **argv) status = EXIT_SUCCESS; out: sqfs_writer_cleanup(&sqfs, status); -out_if: - sqfs_drop(input_file); +out_it: + sqfs_drop(tar); return status; } diff --git a/bin/tar2sqfs/src/tar2sqfs.h b/bin/tar2sqfs/src/tar2sqfs.h index a21774b..e853ae9 100644 --- a/bin/tar2sqfs/src/tar2sqfs.h +++ b/bin/tar2sqfs/src/tar2sqfs.h @@ -15,7 +15,6 @@ #include "tar/tar.h" #include "tar/format.h" #include "xfrm/compress.h" -#include "io/xfrm.h" #include #include @@ -34,6 +33,6 @@ extern char *root_becomes; void process_args(int argc, char **argv); /* process_tarball.c */ -int process_tarball(istream_t *input_file, sqfs_writer_t *sqfs); +int process_tarball(dir_iterator_t *it, sqfs_writer_t *sqfs); #endif /* TAR2SQFS_H */ diff --git a/lib/tar/Makemodule.am b/lib/tar/Makemodule.am index 9061571..4dc5057 100644 --- a/lib/tar/Makemodule.am +++ b/lib/tar/Makemodule.am @@ -173,17 +173,23 @@ test_tar_xattr_schily_bin_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) test_tar_xattr_schily_bin_CPPFLAGS += -DTESTFILE=xattr/xattr-schily-binary.tar test_tar_iterator_SOURCES = lib/tar/test/tar_iterator.c -test_tar_iterator_LDADD = libtar.a libsquashfs.la libio.a libutil.a libcompat.a +test_tar_iterator_LDADD = libtar.a libsquashfs.la libxfrm.a libio.a \ + libutil.a libcompat.a $(XZ_LIBS) $(BZIP2_LIBS) \ + $(ZLIB_LIBS) $(ZSTD_LIBS) test_tar_iterator_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) test_tar_iterator_CPPFLAGS += -DTESTFILE=format-acceptance/gnu.tar test_tar_iterator2_SOURCES = lib/tar/test/tar_iterator2.c -test_tar_iterator2_LDADD = libtar.a libsquashfs.la libio.a libutil.a libcompat.a +test_tar_iterator2_LDADD = libtar.a libsquashfs.la libio.a libxfrm.a \ + libutil.a libcompat.a $(XZ_LIBS) $(BZIP2_LIBS) \ + $(ZLIB_LIBS) $(ZSTD_LIBS) test_tar_iterator2_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) test_tar_iterator2_CPPFLAGS += -DTESTFILE=iterator/sparse.tar test_tar_iterator3_SOURCES = lib/tar/test/tar_iterator3.c -test_tar_iterator3_LDADD = libtar.a libsquashfs.la libio.a libutil.a libcompat.a +test_tar_iterator3_LDADD = libtar.a libsquashfs.la libio.a libxfrm.a \ + libutil.a libcompat.a $(XZ_LIBS) $(BZIP2_LIBS) \ + $(ZLIB_LIBS) $(ZSTD_LIBS) test_tar_iterator3_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR) tar_fuzz_SOURCES = lib/tar/test/tar_fuzz.c diff --git a/lib/tar/src/iterator.c b/lib/tar/src/iterator.c index 216c528..85937c8 100644 --- a/lib/tar/src/iterator.c +++ b/lib/tar/src/iterator.c @@ -4,10 +4,13 @@ * * Copyright (C) 2023 David Oberhollenzer */ +#include "xfrm/compress.h" +#include "tar/format.h" #include "tar/tar.h" #include "sqfs/error.h" #include "sqfs/xattr.h" #include "util/util.h" +#include "io/xfrm.h" #include #include @@ -311,16 +314,45 @@ static void it_destroy(sqfs_object_t *obj) free(tar); } -dir_iterator_t *tar_open_stream(istream_t *stream) +/*****************************************************************************/ + +static int tar_probe(const sqfs_u8 *data, size_t size) +{ + size_t i, offset; + + if (size >= TAR_RECORD_SIZE) { + for (i = 0; i < TAR_RECORD_SIZE; ++i) { + if (data[i] != 0x00) + break; + } + + if (i == TAR_RECORD_SIZE) { + data += TAR_RECORD_SIZE; + size -= TAR_RECORD_SIZE; + } + } + + offset = offsetof(tar_header_t, magic); + + if (offset + 5 <= size) { + if (memcmp(data + offset, "ustar", 5) == 0) + return 1; + } + + return 0; +} + +dir_iterator_t *tar_open_stream(istream_t *strm) { tar_iterator_t *tar = calloc(1, sizeof(*tar)); dir_iterator_t *it = (dir_iterator_t *)tar; + xfrm_stream_t *xfrm = NULL; + int ret; if (tar == NULL) return NULL; sqfs_object_init(it, it_destroy, NULL); - tar->stream = sqfs_grab(stream); it->next = it_next; it->read_link = it_read_link; it->open_subdir = it_open_subdir; @@ -328,5 +360,35 @@ dir_iterator_t *tar_open_stream(istream_t *stream) it->open_file_ro = it_open_file_ro; it->read_xattr = it_read_xattr; + /* proble if the stream is compressed */ + ret = istream_precache(strm); + if (ret != 0) + goto out_strm; + + ret = tar_probe(strm->buffer, strm->buffer_used); + if (ret > 0) + goto out_strm; + + ret = xfrm_compressor_id_from_magic(strm->buffer, strm->buffer_used); + if (ret <= 0) + goto out_strm; + + /* auto-wrap a compressed source stream */ + xfrm = decompressor_stream_create(ret); + if (xfrm == NULL) { + sqfs_drop(it); + return NULL; + } + + tar->stream = istream_xfrm_create(strm, xfrm); + if (tar->stream == NULL) { + sqfs_drop(xfrm); + sqfs_drop(it); + return NULL; + } + + return it; +out_strm: + tar->stream = sqfs_grab(strm); return it; } -- cgit v1.2.3