]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Change the first field of the 'LA' extra block to the full 'version made by'
authorTim Kientzle <kientzle@acm.org>
Tue, 31 Dec 2013 18:11:48 +0000 (10:11 -0800)
committerTim Kientzle <kientzle@acm.org>
Tue, 31 Dec 2013 18:11:48 +0000 (10:11 -0800)
libarchive/archive_read_support_format_zip.c
libarchive/archive_write_set_format_zip.c
libarchive/test/test_write_format_zip_compression_store.c
libarchive/test/test_write_format_zip_file.c
libarchive/test/test_write_format_zip_file_zip64.c

index 3ac6085e82fb6d25585c44cab3be132e6f693148..ae8035cc893153309c4d47b82b49b97966c3317f 100644 (file)
@@ -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
index 220acc0cabd798531c2fb0aa10974d074dc689db..0199023fb61aaab0b4c8acc87d8169ce12c202df 100644 (file)
@@ -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);
index 530464a48a5346a14280339fdef86ff30fa8815c..d08219d407b77418c2dc1d186cf54cd43fff63b3 100644 (file)
@@ -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));
index 7bdc2d3cd5c2da897afcbe66b08fa8484be641b5..903f1f81733a21f58596df333360f0a6dca17fda 100644 (file)
@@ -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. */
index 40c055009d10e965413e21fa03063c82d11e2265..f0e9d6ad193a834a3f05d65c495537ea4cbd6696 100644 (file)
@@ -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. */