]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Add a bitmap to indicate which fields are included for compression and for future...
authorTim Kientzle <kientzle@gmail.com>
Thu, 2 Jan 2014 14:14:20 +0000 (06:14 -0800)
committerTim Kientzle <kientzle@gmail.com>
Thu, 2 Jan 2014 14:14:20 +0000 (06:14 -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..1c653a6085a1972d41f270d8ab113648d6592e6a 100644 (file)
@@ -340,21 +340,51 @@ 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];
+                       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 (datasize >= 2) {
+
+                       if (bitmap & 1) {
+                               // 2 byte "version made by"
+                               if (datasize < 2)
+                                       break;
+                               zip_entry->system
+                                   = archive_le16dec(p + offset) >> 8;
+                               offset += 2;
+                               datasize -= 2;
+                       }
+                       if (bitmap & 2) {
                                // 2 byte "internal file attributes"
+                               uint32_t internal_attributes;
+                               if (datasize < 2)
+                                       break;
+                               internal_attributes
+                                   = archive_le16dec(p + offset);
+                               // Not used by libarchive at present.
+                               (void)internal_attributes; /* UNUSED */
                                offset += 2;
                                datasize -= 2;
                        }
-                       if (datasize >= 4) {
+                       if (bitmap & 4) {
                                // 4 byte "external file attributes"
-                               uint32_t external_attributes
+                               uint32_t external_attributes;
+                               if (datasize < 4)
+                                       break;
+                               external_attributes
                                    = archive_le32dec(p + offset);
                                if (zip_entry->system == 3) {
                                        zip_entry->mode
@@ -363,7 +393,24 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
                                offset += 4;
                                datasize -= 4;
                        }
+                       if (bitmap & 8) {
+                               // 2 byte comment length + comment
+                               uint32_t comment_length;
+                               if (datasize < 2)
+                                       break;
+                               comment_length
+                                   = archive_le16dec(p + offset);
+                               offset += 2;
+                               datasize -= 2;
+
+                               if (datasize < comment_length)
+                                       break;
+                               // Comment is not supported by libarchive
+                               offset += comment_length;
+                               datasize -= comment_length;
+                       }
                        break;
+               }
                case 0x7855:
                        /* Info-ZIP Unix Extra Field (type 2) "Ux". */
 #ifdef DEBUG
index ad4e6b058d2c617afb33043bc7bae89dc4aedbaa..32889e80d773fcac97e08f04ebb372bd280be60b 100644 (file)
@@ -645,8 +645,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[0] = 5; /* bitmap of included fields */
                e += 1;
+               archive_le16enc(e, /* "Version created by" */
+                   3 * 256 + version_needed);
+               e += 2;
                archive_le16enc(e, 0); /* internal file attributes */
                e += 2;
                archive_le32enc(e,  /* external file attributes */
index 1c48620645063a1b39968943c8bfb1c32054ddc1..69cedc4420b625640abfdc9434e91e673bd67149 100644 (file)
@@ -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), 39); /* Extra field length */
+       assertEqualInt(i2(q + 28), 41); /* 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 */
@@ -229,10 +229,11 @@ 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), 9); /* size */
+       assertEqualInt(q[4], 7); /* Bitmap of fields included. */
+       assertEqualInt(i2(q + 5) >> 8, 3); /* system & version made by */
+       assertEqualInt(i2(q + 7), 0); /* internal file attributes */
+       assertEqualInt(i4(q + 9) >> 16 & 01777, file_perm); /* external file attributes */
        q = q + 4 + i2(q + 2);
 
        assert(q == extra_start + i2(local_header + 28));
@@ -298,7 +299,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), 41); /* 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 */
@@ -317,10 +318,11 @@ 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), 9); /* size */
+       assertEqualInt(q[4], 7); /* bitmap of fields */
+       assertEqualInt(i2(q + 5) >> 8, 3); /* system & version made by */
+       assertEqualInt(i2(q + 7), 0); /* internal file attributes */
+       assertEqualInt(i4(q + 9) >> 16 & 01777, folder_perm); /* external file attributes */
        q = q + 4 + i2(q + 2);
 
        assert(q == extra_start + i2(local_header + 28));
index 0216fef3454e20d566b8afc8f491c76ce394fdd6..88a733fb59f206d7d48f258fba89da47a25e0d90 100644 (file)
@@ -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), 35); /* Extra field length */
+       assertEqualInt(i2(p + 28), 37); /* 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,12 @@ DEFINE_TEST(test_write_format_zip_file)
        assertEqualInt(i4(p + 11), file_gid); /* 'Ux' GID */
        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), 0x414c); /* 'LA' experimental extension block */
+       assertEqualInt(i2(p + 2), 9); /* size */
+       assertEqualInt(p[4], 7); /* bitmap of fields in this block */
+       assertEqualInt(i2(p + 5) >> 8, 3); /* System & version made by */
+       assertEqualInt(i2(p + 7), 0); /* internal file attributes */
+       assertEqualInt(i4(p + 9) >> 16 & 01777, file_perm); /* external file attributes */
        p += 4 + i2(p + 2);
 
        /* Just in case: Report any extra extensions. */
index 3dc512ade02c6f647559611f6ffd0cc9ccded4e4..60770653dfe3894cfc3f9c8c0ec845ebdbf4a2b3 100644 (file)
@@ -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), 55); /* Extra field length */
+       assertEqualInt(i2(p + 28), 57); /* 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);
@@ -250,10 +250,11 @@ 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), 9); /* size */
+       assertEqualInt(p[4], 7); /* bitmap of included fields */
+       assertEqualInt(i2(p + 5) >> 8, 3); /* system & version made by */
+       assertEqualInt(i2(p + 7), 0); /* internal file attributes */
+       assertEqualInt(i4(p + 9) >> 16 & 01777, file_perm); /* external file attributes */
        p += 4 + i2(p + 2);
 
        /* Just in case: Report any extra extensions. */