]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Fix a bug in 7zip writer that the writer cannot correctly handle
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sun, 2 Dec 2012 09:10:00 +0000 (18:10 +0900)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sun, 2 Dec 2012 11:09:40 +0000 (20:09 +0900)
large data(more than 60K bytes) in a writing request.

libarchive/archive_write_set_format_7zip.c
libarchive/test/test_write_format_7zip.c

index 3b20d30838f341b55d0b1e994aa40f8127ad03ce..7847cb3c5994f15cc8edc0610d93b64376787c74 100644 (file)
@@ -566,7 +566,7 @@ compress_out(struct archive_write *a, const void *buff, size_t s,
                    (unsigned)s);
        zip->stream.next_in = (const unsigned char *)buff;
        zip->stream.avail_in = s;
-       do {
+       for (;;) {
                /* Compress file data. */
                r = compression_code(&(a->archive), &(zip->stream), run);
                if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
@@ -580,8 +580,12 @@ compress_out(struct archive_write *a, const void *buff, size_t s,
                        if (zip->crc32flg & ENCODED_CRC32)
                                zip->encoded_crc32 = crc32(zip->encoded_crc32,
                                    zip->wbuff, sizeof(zip->wbuff));
+                       if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF)
+                               continue;
                }
-       } while (zip->stream.avail_in);
+               if (zip->stream.avail_in == 0)
+                       break;
+       }
        if (run == ARCHIVE_Z_FINISH) {
                uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out;
                if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK)
index f4bbfb405aa7958d4bdd29f388a80e5e1ddca81a..dd62d9e653d434c4498b30a605f7ca18b8375ef9 100644 (file)
@@ -789,6 +789,106 @@ test_only_empty_files(void)
        free(buff);
 }
 
+#define LARGE_SIZE     (16*1024*1024)
+static void
+test_large(const char *compression_type)
+{
+       static char filedata[LARGE_SIZE];
+       static char filedata2[LARGE_SIZE];
+       struct archive_entry *ae;
+       struct archive *a;
+       size_t used;
+       size_t buffsize = LARGE_SIZE + 1024 * 256;
+       char *buff;
+       unsigned i;
+
+       buff = malloc(buffsize);
+
+       /* Create a new archive in memory. */
+       assert((a = archive_write_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a));
+       if (compression_type != NULL &&
+           ARCHIVE_OK != archive_write_set_format_option(a, "7zip",
+           "compression", compression_type)) {
+               skipping("%s writing not fully supported on this platform",
+                  compression_type);
+               assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+               free(buff);
+               return;
+       }
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a));
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_write_open_memory(a, buff, buffsize, &used));
+
+       /*
+        * Write a large file to it.
+        */
+       assert((ae = archive_entry_new()) != NULL);
+       archive_entry_set_mtime(ae, 1, 100);
+       assertEqualInt(1, archive_entry_mtime(ae));
+       assertEqualInt(100, archive_entry_mtime_nsec(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, sizeof(filedata));
+
+       assertEqualInt(0, archive_write_header(a, ae));
+       archive_entry_free(ae);
+       if (strcmp(compression_type, "ppmd") == 0) {
+               /* NOTE: PPMd cannot handle random data correctly.*/
+               memset(filedata, 'a', sizeof(filedata));
+       } else {
+               for (i = 0; i < sizeof(filedata); i++)
+                       filedata[i] = (char)rand();
+       }
+       assertEqualInt(sizeof(filedata),
+           archive_write_data(a, filedata, sizeof(filedata)));
+
+       /* Close out the archive. */
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+
+       /* Verify the initial header. */
+       assertEqualMem(buff, "\x37\x7a\xbc\xaf\x27\x1c\x00\x03", 8);
+
+       /*
+        * 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));
+
+       /*
+        * Read and verify a large file.
+        */
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualInt(1, archive_entry_mtime(ae));
+       assertEqualInt(100, archive_entry_mtime_nsec(ae));
+       assertEqualInt(0, archive_entry_atime(ae));
+       assertEqualInt(0, archive_entry_ctime(ae));
+       assertEqualString("file", archive_entry_pathname(ae));
+       assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
+       assertEqualInt(sizeof(filedata), archive_entry_size(ae));
+       assertEqualIntA(a, sizeof(filedata2),
+           archive_read_data(a, filedata2, sizeof(filedata2)));
+       assertEqualMem(filedata, filedata2, sizeof(filedata));
+
+       /* Verify the end of the archive. */
+       assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+       /* Verify archive format. */
+       assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
+       assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a));
+
+       assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+
+       free(buff);
+}
+
 DEFINE_TEST(test_write_format_7zip)
 {
        /* Test that making a 7-Zip archive file by default compression
@@ -814,3 +914,39 @@ DEFINE_TEST(test_write_format_7zip)
        test_only_empty_file();
        test_only_empty_files();
 }
+
+DEFINE_TEST(test_write_format_7zip_large_copy)
+{
+       /* Test that making a 7-Zip archive file without compression. */
+       test_large("copy");
+}
+
+DEFINE_TEST(test_write_format_7zip_large_deflate)
+{
+       /* Test that making a 7-Zip archive file with deflate compression. */
+       test_large("deflate");
+}
+
+DEFINE_TEST(test_write_format_7zip_large_bzip2)
+{
+       /* Test that making a 7-Zip archive file with bzip2 compression. */
+       test_large("bzip2");
+}
+
+DEFINE_TEST(test_write_format_7zip_large_lzma1)
+{
+       /* Test that making a 7-Zip archive file with lzma1 compression. */
+       test_large("lzma1");
+}
+
+DEFINE_TEST(test_write_format_7zip_large_lzma2)
+{
+       /* Test that making a 7-Zip archive file with lzma2 compression. */
+       test_large("lzma2");
+}
+
+DEFINE_TEST(test_write_format_7zip_large_ppmd)
+{
+       /* Test that making a 7-Zip archive file with PPMd compression. */
+       test_large("ppmd");
+}