From: Tim Kientzle Date: Sun, 12 Jan 2014 17:18:57 +0000 (-0800) Subject: Merge branch 'master' of github.com:kientzle/libarchive-zip64 X-Git-Tag: v3.1.900a~327^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=29362aff96643dd5d33cd5fc453c7adcdf61d2c9;p=thirdparty%2Flibarchive.git Merge branch 'master' of github.com:kientzle/libarchive-zip64 --- 29362aff96643dd5d33cd5fc453c7adcdf61d2c9 diff --cc libarchive/archive_read_support_format_zip.c index ae8035cc8,b3ccf7c00..37fbeb14e --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@@ -339,19 -339,29 +339,37 @@@ process_extra(const char *p, size_t ext } break; } - case 0x414C: + case 0x6c65: { - /* Experimental 'LA' field */ + /* Experimental 'el' field */ + /* + * Introduced Dec 2013 to provide a way to + * include external file attributes in local file + * header. This provides file type and permission + * information necessary to support full streaming + * extraction. Currently being discussed with + * other Zip developers... subject to change. + */ - if (datasize >= 2) { + int bitmap, bitmap_last; + + if (datasize < 1) + break; + bitmap_last = bitmap = 0xff & p[offset]; + offset += 1; + datasize -= 1; + + /* We only support first 7 bits of bitmap; skip rest. */ + while ((bitmap_last & 0x80) != 0 + && datasize >= 1) { + bitmap_last = p[offset]; + offset += 1; + datasize -= 1; + } + + if (bitmap & 1) { // 2 byte "version made by" + if (datasize < 2) + break; zip_entry->system = archive_le16dec(p + offset) >> 8; offset += 2; diff --cc libarchive/archive_write_set_format_zip.c index 0199023fb,11656f083..5a32b9df9 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@@ -272,14 -249,13 +263,19 @@@ archive_write_zip_options(struct archiv } return (ret); } else if (strcmp(key, "zip64") == 0) { + /* + * Bias decisions about Zip64: force them to be + * generated in certain cases where they are not + * forbidden or avoid them in certain cases where they + * are not strictly required. + */ - zip->force_zip64 = (val != NULL && *val != '\0'); - zip->avoid_zip64 = !zip->force_zip64; + if (val != NULL && *val != '\0') { + zip->flags |= ZIP_FLAG_FORCE_ZIP64; + zip->flags &= ~ZIP_FLAG_AVOID_ZIP64; + } else { + zip->flags &= ~ZIP_FLAG_FORCE_ZIP64; + zip->flags |= ZIP_FLAG_AVOID_ZIP64; + } return (ARCHIVE_OK); } @@@ -426,6 -401,6 +421,23 @@@ archive_write_zip_header(struct archive return ARCHIVE_FAILED; }; ++ /* If we're not using Zip64, reject large files. */ ++ if (zip->flags & ZIP_FLAG_AVOID_ZIP64) { ++ /* Reject entries over 4GB. */ ++ if (archive_entry_size_is_set(entry) ++ && (archive_entry_size(entry) > 0xffffffff)) { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, ++ "Files > 4GB require Zip64 extensions"); ++ return ARCHIVE_FAILED; ++ } ++ /* Reject entries if archive is > 4GB. */ ++ if (zip->written_bytes > 0xffffffff) { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, ++ "Archives > 4GB require Zip64 extensions"); ++ return ARCHIVE_FAILED; ++ } ++ } ++ /* Only regular files can have size > 0. */ if (type != AE_IFREG) archive_entry_set_size(entry, 0); diff --cc libarchive/test/test_write_format_zip.c index fc91f8550,31c611fef..4c94e123b --- a/libarchive/test/test_write_format_zip.c +++ b/libarchive/test/test_write_format_zip.c @@@ -581,10 -581,9 +581,12 @@@ DEFINE_TEST(test_write_format_zip64 assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:zip64")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:zip64")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "zip:experimental")); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used)); write_contents(a);