From: Tim Kientzle Date: Tue, 31 Dec 2013 04:51:26 +0000 (-0800) Subject: A couple of changes to the experimental new extra block, as suggested by Steven Schweda. X-Git-Tag: v3.1.900a~327^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7a90a129c6094d500504433ea74f5fd71c197016;p=thirdparty%2Flibarchive.git A couple of changes to the experimental new extra block, as suggested by Steven Schweda. * Name changed from 'at' to 'LA' (Local Attributes) * Trimmed 'version made by' down to just 1 byte system code --- diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index b0d7858d3..3ac6085e8 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -339,13 +339,13 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) } break; } - case 0x7461: - /* Experimental 'at' field */ - if (datasize >= 2) { - zip_entry->system - = archive_le16dec(p + offset) >> 8; - offset += 2; - datasize -= 2; + case 0x414C: + /* Experimental 'LA' field */ + if (datasize >= 1) { + // 1 byte system identifier + zip_entry->system = p[offset]; + offset += 1; + datasize -= 1; } if (datasize >= 2) { // 2 byte "internal file attributes" @@ -353,6 +353,7 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) datasize -= 2; } if (datasize >= 4) { + // 4 byte "external file attributes" uint32_t external_attributes = archive_le32dec(p + offset); if (zip_entry->system == 3) { diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index f28c59ea7..ad4e6b058 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -576,6 +576,10 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) memset(local_extra, 0, sizeof(local_extra)); e = local_extra; + /* First, extra blocks that are the same between + * the local file header and the central directory. + * We format them once and then duplicate them. */ + /* UT timestamp, length depends on what timestamps are set. */ memcpy(e, "UT", 2); archive_le16enc(e + 2, @@ -613,12 +617,17 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) e += 4; /* Copy UT and ux into central directory as well. */ - /* (Zip64 extended data varies between local header and - * central directory, so we cannot just copy it.) */ zip->file_header_extra_offset = zip->central_directory_bytes; cd_extra = cd_alloc(zip, e - local_extra); memcpy(cd_extra, local_extra, e - local_extra); + /* + * Following extra blocks vary between local header and + * central directory. These are the local header versions. + * Central directory versions get formatted in + * archive_write_zip_finish_entry() below. + */ + /* "[Zip64 entry] in the local header MUST include BOTH * original [uncompressed] and compressed size fields." */ if (zip->entry_uses_zip64) { @@ -632,13 +641,12 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) archive_le16enc(zip64_start + 2, e - (zip64_start + 4)); } - { /* Experimental 'at' extension to support streaming. */ + { /* Experimental 'LA' extension to improve streaming. */ unsigned char *external_info = e; - memcpy(e, "at\000\000", 4); + memcpy(e, "LA\000\000", 4); // 0x414C + 2-byte length e += 4; - archive_le16enc(e, /* system + version written by */ - 3 * 256 + version_needed); - e += 2; + e[0] = 3; /* system */ + e += 1; archive_le16enc(e, 0); /* internal file attributes */ e += 2; archive_le32enc(e, /* external file attributes */ diff --git a/libarchive/test/test_write_format_zip_compression_store.c b/libarchive/test/test_write_format_zip_compression_store.c index 2aa4146e9..1c4862064 100644 --- a/libarchive/test/test_write_format_zip_compression_store.c +++ b/libarchive/test/test_write_format_zip_compression_store.c @@ -209,7 +209,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), 40); /* Extra field length */ + assertEqualInt(i2(q + 28), 39); /* 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 */ @@ -228,11 +228,11 @@ DEFINE_TEST(test_write_format_zip_compression_store) assertEqualInt(i4(q + 11), file_gid); /* 'Ux' GID */ q = q + 4 + i2(q + 2); - assertEqualInt(i2(q), 0x7461); /* 'at' experimental extension header */ - assertEqualInt(i2(q + 2), 8); /* 'at' size */ - assertEqualInt(i2(q + 4), 3 * 256 + 10); /* version made by */ - assertEqualInt(i2(q + 6), 0); /* internal file attributes */ - assertEqualInt(i4(q + 8) >> 16 & 01777, file_perm); /* external file attributes */ + 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 */ q = q + 4 + i2(q + 2); assert(q == extra_start + i2(local_header + 28)); @@ -298,7 +298,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), 40); /* Extra field length */ + assertEqualInt(i2(q + 28), 39); /* 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 */ @@ -316,11 +316,11 @@ DEFINE_TEST(test_write_format_zip_compression_store) assertEqualInt(i4(q + 11), folder_gid); /* 'ux' GID */ q = q + 4 + i2(q + 2); - assertEqualInt(i2(q), 0x7461); /* 'at' experimental extension header */ - assertEqualInt(i2(q + 2), 8); /* 'at' size */ - assertEqualInt(i2(q + 4), 3 * 256 + 20); /* version made by */ - assertEqualInt(i2(q + 6), 0); /* internal file attributes */ - assertEqualInt(i4(q + 8) >> 16 & 01777, folder_perm); /* external file attributes */ + 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 */ 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 7825ef55b..0216fef34 100644 --- a/libarchive/test/test_write_format_zip_file.c +++ b/libarchive/test/test_write_format_zip_file.c @@ -196,7 +196,7 @@ 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), 36); /* Extra field length */ + assertEqualInt(i2(p + 28), 35); /* 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); @@ -216,11 +216,11 @@ DEFINE_TEST(test_write_format_zip_file) assertEqualInt(i4(p + 11), file_gid); /* 'Ux' GID */ p += 4 + i2(p + 2); - assertEqualInt(i2(p), 0x7461); /* 'at' experimental extension header */ - assertEqualInt(i2(p + 2), 8); /* 'at' size */ - assertEqualInt(i2(p + 4), 3 * 256 + 20); /* version made by */ - assertEqualInt(i2(p + 6), 0); /* internal file attributes */ - assertEqualInt(i4(p + 8) >> 16 & 01777, file_perm); /* external file attributes */ + 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 */ 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 1f47040b1..3dc512ade 100644 --- a/libarchive/test/test_write_format_zip_file_zip64.c +++ b/libarchive/test/test_write_format_zip_file_zip64.c @@ -223,7 +223,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), 56); /* Extra field length */ + assertEqualInt(i2(p + 28), 55); /* 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); @@ -249,11 +249,11 @@ DEFINE_TEST(test_write_format_zip_file_zip64) /* compressed file size we can't verify here */ p += 4 + i2(p + 2); - assertEqualInt(i2(p), 0x7461); /* 'at' experimental extension header */ - assertEqualInt(i2(p + 2), 8); /* 'at' size */ - assertEqualInt(i2(p + 4), 3 * 256 + 45); /* version made by */ - assertEqualInt(i2(p + 6), 0); /* internal file attributes */ - assertEqualInt(i4(p + 8) >> 16 & 01777, file_perm); /* external file attributes */ + 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 */ p += 4 + i2(p + 2); /* Just in case: Report any extra extensions. */