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);
}
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);
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);
}