Set the ZIP version in the Central File Directory to UNIX
- Correctly set ZIP version in the Central File Directory so that the external_attributes field is correctly interpreted as a unix file mode
- Add unit tests to verify permissions are maintained
Fixes #2074
Closes #6375.
PiperOrigin-RevId: 218493221
diff --git a/third_party/ijar/test/zip_test.sh b/third_party/ijar/test/zip_test.sh
index d70fa8f..a938556 100755
--- a/third_party/ijar/test/zip_test.sh
+++ b/third_party/ijar/test/zip_test.sh
@@ -188,4 +188,27 @@
|| fail "Unzip after zipper output is not expected"
}
+function test_zipper_permissions() {
+ local -r LOCAL_TEST_DIR="${TEST_TMPDIR}/${FUNCNAME[0]}"
+ mkdir -p ${LOCAL_TEST_DIR}/files
+ printf "#!/bin/sh\nexit 0\n" > ${LOCAL_TEST_DIR}/files/executable
+ printf "#!/bin/sh\nexit 0\n" > ${LOCAL_TEST_DIR}/files/non_executable
+ chmod +x ${LOCAL_TEST_DIR}/files/executable
+ chmod -x ${LOCAL_TEST_DIR}/files/non_executable
+
+ ${ZIPPER} cC ${LOCAL_TEST_DIR}/output.zip \
+ executable=${LOCAL_TEST_DIR}/files/executable \
+ non_executable=${LOCAL_TEST_DIR}/files/non_executable
+
+ mkdir -p ${LOCAL_TEST_DIR}/out
+ cd ${LOCAL_TEST_DIR}/out && $UNZIP -q ${LOCAL_TEST_DIR}/output.zip
+
+ if ! test -x ${LOCAL_TEST_DIR}/out/executable; then
+ fail "out/executable should have been executable"
+ fi
+ if test -x ${LOCAL_TEST_DIR}/out/non_executable; then
+ fail "out/non_executable should not have been executable"
+ fi
+}
+
run_suite "zipper tests"
diff --git a/third_party/ijar/zip.cc b/third_party/ijar/zip.cc
index 3bc66b5..ec29bed 100644
--- a/third_party/ijar/zip.cc
+++ b/third_party/ijar/zip.cc
@@ -41,6 +41,7 @@
#define LOCAL_FILE_HEADER_SIGNATURE 0x04034b50
#define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50
+#define UNIX_ZIP_FILE_VERSION 0x0300
#define DIGITAL_SIGNATURE 0x05054b50
#define ZIP64_EOCD_SIGNATURE 0x06064b50
#define ZIP64_EOCD_LOCATOR_SIGNATURE 0x07064b50
@@ -893,7 +894,7 @@
for (size_t ii = 0; ii < entries_.size(); ++ii) {
LocalFileEntry *entry = entries_[ii];
put_u4le(q, CENTRAL_FILE_HEADER_SIGNATURE);
- put_u2le(q, 0); // version made by
+ put_u2le(q, UNIX_ZIP_FILE_VERSION);
put_u2le(q, ZIP_VERSION_TO_EXTRACT); // version to extract
put_u2le(q, 0); // general purpose bit flag
@@ -924,7 +925,7 @@
put_u4le(q, ZIP64_EOCD_SIGNATURE);
// signature and size field doesn't count towards size
put_u8le(q, ZIP64_EOCD_FIXED_SIZE - 12);
- put_u2le(q, 0); // version made by
+ put_u2le(q, UNIX_ZIP_FILE_VERSION); // version made by
put_u2le(q, 0); // version needed to extract
put_u4le(q, 0); // number of this disk
put_u4le(q, 0); // # of the disk with the start of the central directory