]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
New functionality added for automatically choose write file format and filter by...
authorKirill Okhotnikov <kirill.okhotnikov@gmail.com>
Mon, 9 Feb 2015 12:37:14 +0000 (13:37 +0100)
committerKirill Okhotnikov <kirill.okhotnikov@gmail.com>
Mon, 9 Feb 2015 12:37:14 +0000 (13:37 +0100)
Makefile.am
libarchive/CMakeLists.txt
libarchive/archive.h
libarchive/archive_write_set_format_filter_by_ext.c [new file with mode: 0644]
libarchive/test/CMakeLists.txt
libarchive/test/test_archive_write_set_format_filter_by_ext.c [new file with mode: 0644]

index 0a3cd3192218ce70ff36e1ef6885c0feb10ba8f6..541c94889d247b59dddc248b55cfb95b4ef8e675 100644 (file)
@@ -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 \
index 140e75b2d6d5a9fb7b2eac3bab63962c6c32885e..b9d09b9ff4e87d1c01f286c387d81099b2c5e387 100644 (file)
@@ -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
index 1f0fc3874313a12208f3a5d743d400bc959b5f26..d5ea01766e73a107d3082c241ed52527b65834d9 100644 (file)
@@ -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 (file)
index 0000000..e4a9d9f
--- /dev/null
@@ -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 <sys/types.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#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);
+}
+
+
+
+
index 045e3e164d8982118efe93abec7ae25f6d2bd778..5a6d2cfe80ac7d3267089f938957d24ae99df848 100644 (file)
@@ -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 (file)
index 0000000..c073505
--- /dev/null
@@ -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");
+}