From: Tim Kientzle Date: Tue, 31 Dec 2013 18:11:48 +0000 (-0800) Subject: Change the first field of the 'LA' extra block to the full 'version made by' X-Git-Tag: v3.1.900a~327^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6f8a037c1aee584b49d49f7a9ce81c9e7a138c93;p=thirdparty%2Flibarchive.git Change the first field of the 'LA' extra block to the full 'version made by' --- diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 3ac6085e8..ae8035cc8 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -340,15 +340,26 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) break; } case 0x414C: + { /* Experimental 'LA' field */ - if (datasize >= 1) { - // 1 byte system identifier - zip_entry->system = p[offset]; - offset += 1; - datasize -= 1; + /* + * 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) { + // 2 byte "version made by" + zip_entry->system + = archive_le16dec(p + offset) >> 8; + offset += 2; + datasize -= 2; } if (datasize >= 2) { // 2 byte "internal file attributes" + // Not yet used. offset += 2; datasize -= 2; } @@ -364,6 +375,7 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) datasize -= 4; } break; + } case 0x7855: /* Info-ZIP Unix Extra Field (type 2) "Ux". */ #ifdef DEBUG diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index 220acc0ca..0199023fb 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -416,6 +416,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) int64_t size; mode_t type; int version_needed = 10; + int version_made_by = 45; /* We support features from PKZip 4.5 */ /* Ignore types of entries that we don't support. */ type = archive_entry_filetype(entry); @@ -687,9 +688,11 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) unsigned char *external_info = e; memcpy(e, "LA\000\000", 4); // 0x414C + 2-byte length e += 4; - e[0] = 3; /* system */ - e += 1; - archive_le16enc(e, 0); /* internal file attributes */ + /* Version made by */ + archive_le16enc(e, 3 * 256 + version_made_by); + e += 2; + /* internal file attributes */ + archive_le16enc(e, 0); e += 2; archive_le32enc(e, /* external file attributes */ archive_entry_mode(zip->entry) << 16); diff --git a/libarchive/test/test_write_format_zip_compression_store.c b/libarchive/test/test_write_format_zip_compression_store.c index 530464a48..d08219d40 100644 --- a/libarchive/test/test_write_format_zip_compression_store.c +++ b/libarchive/test/test_write_format_zip_compression_store.c @@ -212,7 +212,7 @@ DEFINE_TEST(test_write_format_zip_compression_store) assertEqualInt(i4(q + 18), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */ assertEqualInt(i4(q + 22), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */ assertEqualInt(i2(q + 26), strlen(file_name)); /* Pathname length */ - assertEqualInt(i2(q + 28), 39); /* Extra field length */ + assertEqualInt(i2(q + 28), 40); /* Extra field length */ assertEqualMem(q + 30, file_name, strlen(file_name)); /* Pathname */ extra_start = q = q + 30 + strlen(file_name); assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */ @@ -232,10 +232,10 @@ DEFINE_TEST(test_write_format_zip_compression_store) q = q + 4 + i2(q + 2); assertEqualInt(i2(q), 0x414c); /* 'LA' experimental extension header */ - assertEqualInt(i2(q + 2), 7); /* size */ - assertEqualInt(q[4], 3); /* system */ - assertEqualInt(i2(q + 5), 0); /* internal file attributes */ - assertEqualInt(i4(q + 7) >> 16 & 01777, file_perm); /* external file attributes */ + assertEqualInt(i2(q + 2), 8); /* size */ + assertEqualInt(i2(q + 4) >> 8, 3); /* system */ + assertEqualInt(i2(q + 6), 0); /* internal file attributes */ + assertEqualInt(i4(q + 8) >> 16 & 01777, file_perm); /* external file attributes */ q = q + 4 + i2(q + 2); assert(q == extra_start + i2(local_header + 28)); @@ -301,7 +301,7 @@ DEFINE_TEST(test_write_format_zip_compression_store) assertEqualInt(i4(q + 18), 0); /* Compressed size */ assertEqualInt(i4(q + 22), 0); /* Uncompressed size */ assertEqualInt(i2(q + 26), strlen(folder_name)); /* Pathname length */ - assertEqualInt(i2(q + 28), 39); /* Extra field length */ + assertEqualInt(i2(q + 28), 40); /* Extra field length */ assertEqualMem(q + 30, folder_name, strlen(folder_name)); /* Pathname */ extra_start = q = q + 30 + strlen(folder_name); assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */ @@ -320,10 +320,10 @@ DEFINE_TEST(test_write_format_zip_compression_store) q = q + 4 + i2(q + 2); assertEqualInt(i2(q), 0x414c); /* 'LA' experimental extension header */ - assertEqualInt(i2(q + 2), 7); /* size */ - assertEqualInt(q[4], 3); /* system */ - assertEqualInt(i2(q + 5), 0); /* internal file attributes */ - assertEqualInt(i4(q + 7) >> 16 & 01777, folder_perm); /* external file attributes */ + assertEqualInt(i2(q + 2), 8); /* size */ + assertEqualInt(i2(q + 4) >> 8, 3); /* system */ + assertEqualInt(i2(q + 6), 0); /* internal file attributes */ + assertEqualInt(i4(q + 8) >> 16 & 01777, folder_perm); /* external file attributes */ q = q + 4 + i2(q + 2); assert(q == extra_start + i2(local_header + 28)); diff --git a/libarchive/test/test_write_format_zip_file.c b/libarchive/test/test_write_format_zip_file.c index 7bdc2d3cd..903f1f817 100644 --- a/libarchive/test/test_write_format_zip_file.c +++ b/libarchive/test/test_write_format_zip_file.c @@ -198,19 +198,19 @@ DEFINE_TEST(test_write_format_zip_file) /* assertEqualInt(i4(p + 18), sizeof(file_data)); */ /* Compressed size */ /* assertEqualInt(i4(p + 22), sizeof(file_data)); */ /* Uncompressed size not stored because we're using length-at-end. */ assertEqualInt(i2(p + 26), strlen(file_name)); /* Pathname length */ - assertEqualInt(i2(p + 28), 35); /* Extra field length */ + assertEqualInt(i2(p + 28), 36); /* Extra field length */ assertEqualMem(p + 30, file_name, strlen(file_name)); /* Pathname */ p = extension_start = local_header + 30 + strlen(file_name); extension_end = extension_start + i2(local_header + 28); assertEqualInt(i2(p), 0x5455); /* 'UT' extension header */ - assertEqualInt(i2(p + 2), 5); /* 'UT' size */ + assertEqualInt(i2(p + 2), 5); /* size */ assertEqualInt(p[4], 1); /* 'UT' flags */ assertEqualInt(i4(p + 5), t); /* 'UT' mtime */ p += 4 + i2(p + 2); assertEqualInt(i2(p), 0x7875); /* 'ux' extension header */ - assertEqualInt(i2(p + 2), 11); /* 'ux' size */ + assertEqualInt(i2(p + 2), 11); /* size */ assertEqualInt(p[4], 1); /* 'ux' version */ assertEqualInt(p[5], 4); /* 'ux' uid size */ assertEqualInt(i4(p + 6), file_uid); /* 'Ux' UID */ @@ -219,10 +219,10 @@ DEFINE_TEST(test_write_format_zip_file) p += 4 + i2(p + 2); assertEqualInt(i2(p), 0x414c); /* 'LA' experimental extension header */ - assertEqualInt(i2(p + 2), 7); /* 'at' size */ - assertEqualInt(p[4], 3); /* system */ - assertEqualInt(i2(p + 5), 0); /* internal file attributes */ - assertEqualInt(i4(p + 7) >> 16 & 01777, file_perm); /* external file attributes */ + assertEqualInt(i2(p + 2), 8); /* size */ + assertEqualInt(i2(p + 4) >> 8, 3); /* system */ + assertEqualInt(i2(p + 6), 0); /* internal file attributes */ + assertEqualInt(i4(p + 8) >> 16 & 01777, file_perm); /* external file attributes */ p += 4 + i2(p + 2); /* Just in case: Report any extra extensions. */ diff --git a/libarchive/test/test_write_format_zip_file_zip64.c b/libarchive/test/test_write_format_zip_file_zip64.c index 40c055009..f0e9d6ad1 100644 --- a/libarchive/test/test_write_format_zip_file_zip64.c +++ b/libarchive/test/test_write_format_zip_file_zip64.c @@ -226,7 +226,7 @@ DEFINE_TEST(test_write_format_zip_file_zip64) /* assertEqualInt(i4(p + 18), sizeof(file_data)); */ /* Compressed size */ /* assertEqualInt(i4(p + 22), sizeof(file_data)); */ /* Uncompressed size not stored because we're using length-at-end. */ assertEqualInt(i2(p + 26), strlen(file_name)); /* Pathname length */ - assertEqualInt(i2(p + 28), 55); /* Extra field length */ + assertEqualInt(i2(p + 28), 56); /* Extra field length */ assertEqualMem(p + 30, file_name, strlen(file_name)); /* Pathname */ p = extension_start = local_header + 30 + strlen(file_name); extension_end = extension_start + i2(local_header + 28); @@ -253,10 +253,10 @@ DEFINE_TEST(test_write_format_zip_file_zip64) p += 4 + i2(p + 2); assertEqualInt(i2(p), 0x414c); /* 'LA' experimental extension header */ - assertEqualInt(i2(p + 2), 7); /* 'at' size */ - assertEqualInt(p[4], 3); /* system */ - assertEqualInt(i2(p + 5), 0); /* internal file attributes */ - assertEqualInt(i4(p + 7) >> 16 & 01777, file_perm); /* external file attributes */ + assertEqualInt(i2(p + 2), 8); /* size */ + assertEqualInt(i2(p + 4) >> 8, 3); /* system */ + assertEqualInt(i2(p + 6), 0); /* internal file attributes */ + assertEqualInt(i4(p + 8) >> 16 & 01777, file_perm); /* external file attributes */ p += 4 + i2(p + 2); /* Just in case: Report any extra extensions. */