From 514e6a6cbd2b4a5f650f155fa24d885cad38ddcb Mon Sep 17 00:00:00 2001 From: Michihiro NAKAJIMA Date: Tue, 20 Mar 2012 13:14:40 +0900 Subject: [PATCH] Fix the bug which the patch for issue 249 made, which bug is that sometimes sumcheck error hppens when listing a CAB file whose compression type is none. - Do not consume extra bytes when the compression type is none. - Improve test_read_format_cab to just read file names, not read file contents such as "bsdtar tf". --- libarchive/archive_read_support_format_cab.c | 58 +++++++------------- libarchive/test/test_read_format_cab.c | 50 +++++++++++++++++ 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index ac400465c..bc866a375 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -1358,46 +1358,25 @@ cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail) struct cab *cab = (struct cab *)(a->format->data); struct cfdata *cfdata; const void *d; - int64_t skipped_bytes; cfdata = cab->entry_cfdata; - if (cfdata->uncompressed_avail == 0 && - cfdata->read_offset > 0) { - /* we've already skipped some bytes before really read. */ - skipped_bytes = cfdata->read_offset; - cfdata->read_offset = 0; - cfdata->uncompressed_bytes_remaining += skipped_bytes; - } else - skipped_bytes = 0; - do { - /* - * Note: '1' here is a performance optimization. - * Recall that the decompression layer returns a count of - * available bytes; asking for more than that forces the - * decompressor to combine reads by copying data. - */ - d = __archive_read_ahead(a, 1, avail); - if (*avail <= 0) { - *avail = truncated_error(a); - return (NULL); - } - if (*avail > cfdata->uncompressed_bytes_remaining) - *avail = cfdata->uncompressed_bytes_remaining; - cfdata->uncompressed_avail = cfdata->uncompressed_size; - cfdata->unconsumed = *avail; - cfdata->sum_ptr = d; - if (skipped_bytes > 0) { - skipped_bytes = - cab_minimum_consume_cfdata(a, skipped_bytes); - if (skipped_bytes < 0) { - *avail = ARCHIVE_FATAL; - return (NULL); - } - continue; - } - } while (0); - + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + d = __archive_read_ahead(a, 1, avail); + if (*avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + if (*avail > cfdata->uncompressed_bytes_remaining) + *avail = cfdata->uncompressed_bytes_remaining; + cfdata->uncompressed_avail = cfdata->uncompressed_size; + cfdata->unconsumed = *avail; + cfdata->sum_ptr = d; return (d); } @@ -1992,6 +1971,11 @@ archive_read_format_cab_read_data_skip(struct archive_read *a) if (bytes_skipped < 0) return (ARCHIVE_FATAL); + /* If the compression type is none(uncompressed), we've already + * consumed data as much as the current entry size. */ + if (cab->entry_cffolder->comptype == COMPTYPE_NONE) + cab->entry_cfdata->unconsumed = 0; + /* This entry is finished and done. */ cab->end_of_entry_cleanup = cab->end_of_entry = 1; return (ARCHIVE_OK); diff --git a/libarchive/test/test_read_format_cab.c b/libarchive/test/test_read_format_cab.c index 8e7d55f84..54dd633f2 100644 --- a/libarchive/test/test_read_format_cab.c +++ b/libarchive/test/test_read_format_cab.c @@ -324,16 +324,66 @@ verify2(const char *refname, enum comp_type comp) assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } +/* + * Skip all file like 'bsdtar tvf foo.cab'. + */ +static void +verify3(const char *refname, enum comp_type comp) +{ + struct archive_entry *ae; + struct archive *a; + char zero[128]; + + memset(zero, 0, sizeof(zero)); + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Verify regular empty. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + if (comp != STORE) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + } + /* Verify regular file1. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* Verify regular file2. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* End of archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + if (comp != STORE) { + assertEqualInt(4, archive_file_count(a)); + } else { + assertEqualInt(3, archive_file_count(a)); + } + + /* Verify archive format. */ + assertEqualIntA(a, ARCHIVE_COMPRESSION_NONE, archive_compression(a)); + assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); + + /* Close the archive. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + DEFINE_TEST(test_read_format_cab) { /* Verify Cabinet file in no compression. */ verify("test_read_format_cab_1.cab", STORE); verify2("test_read_format_cab_1.cab", STORE); + verify3("test_read_format_cab_1.cab", STORE); /* Verify Cabinet file in MSZIP. */ verify("test_read_format_cab_2.cab", MSZIP); verify2("test_read_format_cab_2.cab", MSZIP); + verify3("test_read_format_cab_2.cab", MSZIP); /* Verify Cabinet file in LZX. */ verify("test_read_format_cab_3.cab", LZX); verify2("test_read_format_cab_3.cab", LZX); + verify3("test_read_format_cab_3.cab", LZX); } -- 2.47.2