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;
}
datasize -= 4;
}
break;
+ }
case 0x7855:
/* Info-ZIP Unix Extra Field (type 2) "Ux". */
#ifdef DEBUG
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);
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);
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 */
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));
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 */
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));
/* 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 */
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. */
/* 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);
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. */