From: Kirill Okhotnikov Date: Mon, 9 Feb 2015 12:37:14 +0000 (+0100) Subject: New functionality added for automatically choose write file format and filter by... X-Git-Tag: v3.1.900a~94^2~1^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ae9a8882333f51dc5fc023121edf61d2c0764491;p=thirdparty%2Flibarchive.git New functionality added for automatically choose write file format and filter by filename. --- diff --git a/Makefile.am b/Makefile.am index 0a3cd3192..541c94889 100644 --- a/Makefile.am +++ b/Makefile.am @@ -212,6 +212,7 @@ libarchive_la_SOURCES= \ libarchive/archive_write_set_format_7zip.c \ libarchive/archive_write_set_format_ar.c \ libarchive/archive_write_set_format_by_name.c \ + libarchive/archive_write_set_format_filter_by_ext.c \ libarchive/archive_write_set_format_cpio.c \ libarchive/archive_write_set_format_cpio_newc.c \ libarchive/archive_write_set_format_iso9660.c \ @@ -352,6 +353,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_archive_write_add_filter_by_name.c \ libarchive/test/test_archive_write_set_filter_option.c \ libarchive/test/test_archive_write_set_format_by_name.c \ + libarchive/test/test_archive_write_set_format_filter_by_ext.c \ libarchive/test/test_archive_write_set_format_option.c \ libarchive/test/test_archive_write_set_option.c \ libarchive/test/test_archive_write_set_options.c \ diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index 140e75b2d..b9d09b9ff 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -145,6 +145,7 @@ SET(libarchive_SOURCES archive_write_set_format_warc.c archive_write_set_format_xar.c archive_write_set_format_zip.c + archive_write_set_format_filter_by_ext.c archive_write_set_options.c archive_write_set_passphrase.c archive_xxhash.h diff --git a/libarchive/archive.h b/libarchive/archive.h index 1f0fc3874..d5ea01766 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -766,6 +766,8 @@ __LA_DECL int archive_write_set_format_v7tar(struct archive *); __LA_DECL int archive_write_set_format_warc(struct archive *); __LA_DECL int archive_write_set_format_xar(struct archive *); __LA_DECL int archive_write_set_format_zip(struct archive *); +__LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const char *filename); +__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext); __LA_DECL int archive_write_zip_set_compression_deflate(struct archive *); __LA_DECL int archive_write_zip_set_compression_store(struct archive *); __LA_DECL int archive_write_open(struct archive *, void *, diff --git a/libarchive/archive_write_set_format_filter_by_ext.c b/libarchive/archive_write_set_format_filter_by_ext.c new file mode 100644 index 000000000..e4a9d9f97 --- /dev/null +++ b/libarchive/archive_write_set_format_filter_by_ext.c @@ -0,0 +1,136 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2015 Okhotnikov Kirill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 201168 2009-12-29 06:15:32Z kientzle $"); + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" + +/* A table that maps names to functions. */ +static +struct { const char *name; int (*format)(struct archive *); int (*filter)(struct archive *); } names[] = +{ + { ".7z", archive_write_set_format_7zip, archive_write_add_filter_none}, + { ".zip", archive_write_set_format_zip, archive_write_add_filter_none}, + { ".jar", archive_write_set_format_zip, archive_write_add_filter_none}, + { ".cpio", archive_write_set_format_cpio, archive_write_add_filter_none}, + { ".iso", archive_write_set_format_iso9660, archive_write_add_filter_none}, +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) + { ".a", archive_write_set_format_ar_bsd, archive_write_add_filter_none}, + { ".ar", archive_write_set_format_ar_bsd, archive_write_add_filter_none}, +#else + { ".a", archive_write_set_format_ar_svr4, archive_write_add_filter_none}, + { ".ar", archive_write_set_format_ar_svr4, archive_write_add_filter_none}, +#endif + { ".tar", archive_write_set_format_pax_restricted, archive_write_add_filter_none}, + { ".tgz", archive_write_set_format_pax_restricted, archive_write_add_filter_gzip}, + { ".tar.gz", archive_write_set_format_pax_restricted, archive_write_add_filter_gzip}, + { ".tar.bz2", archive_write_set_format_pax_restricted, archive_write_add_filter_bzip2}, + { ".tar.xz", archive_write_set_format_pax_restricted, archive_write_add_filter_xz}, + { NULL, NULL, NULL } +}; + +static +int cmpsuff(const char *str, const char *suffix) +{ + if ((str == NULL) || (suffix == NULL)) + return -1; + + size_t length_str = strlen(str); + size_t length_suffix = strlen(suffix); + + return (length_str >= length_suffix) ? strcmp(str + (length_str - length_suffix), suffix) : -1; +} + +int get_array_index(const char *name) +{ + int i; + + for (i = 0; names[i].name != NULL; i++) + { + if (cmpsuff(name, names[i].name) == 0) + return i; + } + return -1; + +} + +int +archive_write_set_format_filter_by_ext(struct archive *a, const char *filename) +{ + int names_index = get_array_index(filename); + + if (names_index >= 0) + { + int format_state = (names[names_index].format)(a); + if (format_state == ARCHIVE_OK) + return ((names[names_index].filter)(a)); + else + return format_state; + } + + archive_set_error(a, EINVAL, "No such format '%s'", filename); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} + +int +archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext) +{ + int names_index = get_array_index(filename); + + if (names_index < 0) + names_index = get_array_index(def_ext); + + if (names_index >= 0) + { + int format_state = (names[names_index].format)(a); + if (format_state == ARCHIVE_OK) + return ((names[names_index].filter)(a)); + else + return format_state; + } + + archive_set_error(a, EINVAL, "No such format '%s'", filename); + a->state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} + + + + diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 045e3e164..5a6d2cfe8 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -42,6 +42,7 @@ IF(ENABLE_TEST) test_archive_write_add_filter_by_name.c test_archive_write_set_filter_option.c test_archive_write_set_format_by_name.c + test_archive_write_set_format_filter_by_ext.c test_archive_write_set_format_option.c test_archive_write_set_option.c test_archive_write_set_options.c diff --git a/libarchive/test/test_archive_write_set_format_filter_by_ext.c b/libarchive/test/test_archive_write_set_format_filter_by_ext.c new file mode 100644 index 000000000..c073505f7 --- /dev/null +++ b/libarchive/test/test_archive_write_set_format_filter_by_ext.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * Copyright (c) 2015 Okhotnikov Kirill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "test.h" +__FBSDID("$FreeBSD$"); + +static void +test_format_filter_by_ext(const char *output_file, + int format_id, int filter_id, int dot_stored, char * def_ext) +{ + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t buffsize = 1024 * 1024; + char *buff; + int r; + + assert((buff = malloc(buffsize)) != NULL); + if (buff == NULL) + return; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + if( def_ext == NULL) + r = archive_write_set_format_filter_by_ext(a, output_file); + else + r = archive_write_set_format_filter_by_ext_def(a, output_file, def_ext); + if (r == ARCHIVE_WARN) { + skipping("%s format not fully supported on this platform", + archive_format_name(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } else if (r == ARCHIVE_FATAL && + (strcmp(archive_error_string(a), + "lzma compression not supported on this platform") == 0 || + strcmp(archive_error_string(a), + "xz compression not supported on this platform") == 0)) { + const char *filter_name = archive_filter_name(a, 0); + skipping("%s filter not suported on this platform", filter_name); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } else { + if (!assertEqualIntA(a, ARCHIVE_OK, r)) { + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + } + + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + assertEqualInt(1, archive_entry_mtime(ae)); + archive_entry_set_ctime(ae, 1, 0); + assertEqualInt(1, archive_entry_ctime(ae)); + archive_entry_set_atime(ae, 1, 0); + assertEqualInt(1, archive_entry_atime(ae)); + archive_entry_copy_pathname(ae, "file"); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 8); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 8)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + if (format_id > 0) { + /* + * Now, read the data back. + */ + /* With the test memory reader -- seeking mode. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + read_open_memory_seek(a, buff, used, 7)); + + if (dot_stored & 1) { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); + } + /* + * Read and verify the file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + if (dot_stored & 2) { + assertEqualString("./file", archive_entry_pathname(ae)); + } else { + assertEqualString("file", archive_entry_pathname(ae)); + } + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, filter_id, + archive_filter_code(a, 0)); + assertEqualIntA(a, format_id, archive_format(a) & ARCHIVE_FORMAT_BASE_MASK ); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } + free(buff); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_7zip) +{ + test_format_filter_by_ext("./data/test.7z", ARCHIVE_FORMAT_7ZIP, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_zip) +{ + test_format_filter_by_ext("./data/test.zip", ARCHIVE_FORMAT_ZIP, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_jar) +{ + test_format_filter_by_ext("./data/test.jar", ARCHIVE_FORMAT_ZIP, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_a) +{ + test_format_filter_by_ext("./data/test.a", ARCHIVE_FORMAT_AR, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_ar) +{ + test_format_filter_by_ext("./data/test.ar", ARCHIVE_FORMAT_AR, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_cpio) +{ + test_format_filter_by_ext("./data/test.cpio", ARCHIVE_FORMAT_CPIO, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_iso) +{ + test_format_filter_by_ext("./data/test.iso", ARCHIVE_FORMAT_ISO9660, ARCHIVE_FILTER_NONE, 1, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar) +{ + test_format_filter_by_ext("./data/test.tar", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_NONE, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_gz) +{ + test_format_filter_by_ext("./data/test.tar.gz", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_GZIP, 20, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_bz2) +{ + test_format_filter_by_ext("./data/test.tar.bz2", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_BZIP2, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_xz) +{ + test_format_filter_by_ext("./data/test.tar.xz", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_XZ, 0, NULL); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_no_ext_def_zip) +{ + test_format_filter_by_ext("./data/test", ARCHIVE_FORMAT_ZIP, ARCHIVE_FILTER_NONE, 0, ".zip"); +} + +DEFINE_TEST(test_archive_write_set_format_filter_by_ext_tar_bz2_def_zip) +{ + test_format_filter_by_ext("./data/test.tar.bz2", ARCHIVE_FORMAT_TAR, ARCHIVE_FILTER_BZIP2, 0, ".zip"); +}