}
break;
}
- case 0x414C:
+ case 0x6c65:
{
- /* Experimental 'LA' field */
+ /* Experimental 'el' field */
+ /*
+ * 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) {
+ 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 (bitmap & 1) {
// 2 byte "version made by"
+ if (datasize < 2)
+ break;
zip_entry->system
= archive_le16dec(p + offset) >> 8;
offset += 2;
}
return (ret);
} else if (strcmp(key, "zip64") == 0) {
- zip->force_zip64 = (val != NULL && *val != '\0');
- zip->avoid_zip64 = !zip->force_zip64;
+ /*
+ * Bias decisions about Zip64: force them to be
+ * generated in certain cases where they are not
+ * forbidden or avoid them in certain cases where they
+ * are not strictly required.
+ */
+ if (val != NULL && *val != '\0') {
+ zip->flags |= ZIP_FLAG_FORCE_ZIP64;
+ zip->flags &= ~ZIP_FLAG_AVOID_ZIP64;
+ } else {
+ zip->flags &= ~ZIP_FLAG_FORCE_ZIP64;
+ zip->flags |= ZIP_FLAG_AVOID_ZIP64;
+ }
return (ARCHIVE_OK);
}
return ARCHIVE_FAILED;
};
++ /* If we're not using Zip64, reject large files. */
++ if (zip->flags & ZIP_FLAG_AVOID_ZIP64) {
++ /* Reject entries over 4GB. */
++ if (archive_entry_size_is_set(entry)
++ && (archive_entry_size(entry) > 0xffffffff)) {
++ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
++ "Files > 4GB require Zip64 extensions");
++ return ARCHIVE_FAILED;
++ }
++ /* Reject entries if archive is > 4GB. */
++ if (zip->written_bytes > 0xffffffff) {
++ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
++ "Archives > 4GB require Zip64 extensions");
++ return ARCHIVE_FAILED;
++ }
++ }
++
/* Only regular files can have size > 0. */
if (type != AE_IFREG)
archive_entry_set_size(entry, 0);
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a));
assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a));
- assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:zip64"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_options(a, "zip:zip64"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_options(a, "zip:experimental"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_options(a, "zip:experimental"));
assertEqualIntA(a, ARCHIVE_OK,
archive_write_open_memory(a, buff, buffsize, &used));
write_contents(a);