From 549fc1f687f02ada2b7d6f12bfe8678eedffefb3 Mon Sep 17 00:00:00 2001
From: Stefan Bodewig
Date: Thu, 17 Jul 2008 14:44:30 +0000
Subject: [PATCH] don't trust permissions read from another ZIP file blindly.
PR 42122.
git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@677597 13f79535-47bb-0310-9956-ffa450edef68
---
WHATSNEW | 14 ++++++
docs/manual/CoreTasks/ear.html | 12 ++++++
docs/manual/CoreTasks/jar.html | 12 ++++++
docs/manual/CoreTasks/war.html | 12 ++++++
docs/manual/CoreTasks/zip.html | 12 ++++++
src/etc/testcases/taskdefs/nopermissions.zip | Bin 0 -> 138 bytes
src/etc/testcases/taskdefs/zip.xml | 12 ++++++
.../org/apache/tools/ant/taskdefs/Zip.java | 40 ++++++++++++++++--
src/main/org/apache/tools/zip/ZipEntry.java | 13 +++---
.../apache/tools/ant/taskdefs/ZipTest.java | 31 ++++++++++++++
10 files changed, 149 insertions(+), 9 deletions(-)
create mode 100644 src/etc/testcases/taskdefs/nopermissions.zip
diff --git a/WHATSNEW b/WHATSNEW
index 6a6720983..3b17ff8e5 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -63,6 +63,20 @@ Changes that could break older environments:
set failOnEmptyArchive to false to restore the old behavior.
Bugzilla report 35000.
+ * Ant's family of tasks tries to preserve the existing Unix
+ permissions when updating archives or copying entries from one
+ archive to another.
+ Since not all archiving tools support storing Unix permissions in
+ the same way that is used by Ant, sometimes the permissions read by
+ Ant seem to be 0, which means nobody is allowed to do anything to
+ the file or directory.
+ If Ant now encounters a permission set of 0 it will assume that
+ this is not the intended value and instead apply its own default
+ values. Ant used to create entries with 0 permissions itself.
+ The family of tasks has a new attribute preservce0permissions
+ that can be set to restore the old behavior.
+ Bugzilla Report 42122.
+
Fixed bugs:
-----------
diff --git a/docs/manual/CoreTasks/ear.html b/docs/manual/CoreTasks/ear.html
index 4e5b6bf88..071956605 100644
--- a/docs/manual/CoreTasks/ear.html
+++ b/docs/manual/CoreTasks/ear.html
@@ -185,6 +185,18 @@ to a value other than its default, "add"
.
(maximum compression/slowest). Since Ant 1.7
No |
+
+ preserve0permissions |
+ when updating an archive or adding entries from a
+ different archive Ant will assume that a Unix permissions value of
+ 0 (nobody is allowed to do anything to the file/directory) means
+ that the permissions haven't been stored at all rather than real
+ permissions and will instead apply its own default values.
+ Set this attribute to true if you really want to preserve the
+ original permission field.since Ant 1.8.0
+ |
+ No, default is false |
+
Nested elements
diff --git a/docs/manual/CoreTasks/jar.html b/docs/manual/CoreTasks/jar.html
index 5d7081855..68cb0c1ec 100644
--- a/docs/manual/CoreTasks/jar.html
+++ b/docs/manual/CoreTasks/jar.html
@@ -239,6 +239,18 @@ to a value other than its default, "add"
.
Since Ant 1.7.1
No, defaults to ignore. |
+
+ preserve0permissions |
+ when updating an archive or adding entries from a
+ different archive Ant will assume that a Unix permissions value of
+ 0 (nobody is allowed to do anything to the file/directory) means
+ that the permissions haven't been stored at all rather than real
+ permissions and will instead apply its own default values.
+ Set this attribute to true if you really want to preserve the
+ original permission field.since Ant 1.8.0
+ |
+ No, default is false |
+
Nested elements
diff --git a/docs/manual/CoreTasks/war.html b/docs/manual/CoreTasks/war.html
index bd2b5a731..0315df546 100644
--- a/docs/manual/CoreTasks/war.html
+++ b/docs/manual/CoreTasks/war.html
@@ -202,6 +202,18 @@ to a value other than its default, "add"
.
(maximum compression/slowest). Since Ant 1.7
No |
+
+ preserve0permissions |
+ when updating an archive or adding entries from a
+ different archive Ant will assume that a Unix permissions value of
+ 0 (nobody is allowed to do anything to the file/directory) means
+ that the permissions haven't been stored at all rather than real
+ permissions and will instead apply its own default values.
+ Set this attribute to true if you really want to preserve the
+ original permission field.since Ant 1.8.0
+ |
+ No, default is false |
+
Nested elements
diff --git a/docs/manual/CoreTasks/zip.html b/docs/manual/CoreTasks/zip.html
index e2f7e078e..f2e18a80c 100644
--- a/docs/manual/CoreTasks/zip.html
+++ b/docs/manual/CoreTasks/zip.html
@@ -229,6 +229,18 @@ archive.
(maximum compression/slowest). Since Ant 1.7
No |
+
+ preserve0permissions |
+ when updating an archive or adding entries from a
+ different archive Ant will assume that a Unix permissions value of
+ 0 (nobody is allowed to do anything to the file/directory) means
+ that the permissions haven't been stored at all rather than real
+ permissions and will instead apply its own default values.
+ Set this attribute to true if you really want to preserve the
+ original permission field.since Ant 1.8.0
+ |
+ No, default is false |
+
Parameters specified as nested elements
diff --git a/src/etc/testcases/taskdefs/nopermissions.zip b/src/etc/testcases/taskdefs/nopermissions.zip
new file mode 100644
index 0000000000000000000000000000000000000000..979ee68b14343e7f6782ba095158edf5577d8564
GIT binary patch
literal 138
zcmWIWW@h1H0D
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/Zip.java b/src/main/org/apache/tools/ant/taskdefs/Zip.java
index 352faf83e..02e49fb9e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Zip.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Zip.java
@@ -53,6 +53,7 @@ import org.apache.tools.ant.util.GlobPatternMapper;
import org.apache.tools.ant.util.IdentityMapper;
import org.apache.tools.ant.util.MergingMapper;
import org.apache.tools.ant.util.ResourceUtils;
+import org.apache.tools.zip.UnixStat;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipExtraField;
import org.apache.tools.zip.ZipFile;
@@ -139,6 +140,12 @@ public class Zip extends MatchingTask {
private int level = ZipOutputStream.DEFAULT_COMPRESSION;
+ /**
+ * Assume 0 Unix mode is intentional.
+ * @since Ant 1.8.0
+ */
+ private boolean preserve0Permissions = false;
+
/**
* This is the name/location of where to
* create the .zip file.
@@ -401,6 +408,22 @@ public class Zip extends MatchingTask {
roundUp = r;
}
+ /**
+ * Assume 0 Unix mode is intentional.
+ * @since Ant 1.8.0
+ */
+ public void setPreserve0Permissions(boolean b) {
+ preserve0Permissions = b;
+ }
+
+ /**
+ * Assume 0 Unix mode is intentional.
+ * @since Ant 1.8.0
+ */
+ public boolean getPreserve0Permissions() {
+ return preserve0Permissions;
+ }
+
/**
* validate and build
* @throws BuildException on error
@@ -774,8 +797,13 @@ public class Zip extends MatchingTask {
}
if (zf != null) {
ZipEntry ze = zf.getEntry(resources[i].getName());
+ int unixMode = ze.getUnixMode();
+ if ((unixMode == 0 || unixMode == UnixStat.DIR_FLAG)
+ && !preserve0Permissions) {
+ unixMode = dirMode;
+ }
addParentDirs(base, name, zOut, prefix,
- ze.getUnixMode());
+ unixMode);
} else {
ArchiveResource tr = (ArchiveResource) resources[i];
addParentDirs(base, name, zOut, prefix,
@@ -802,10 +830,16 @@ public class Zip extends MatchingTask {
InputStream is = null;
try {
is = zf.getInputStream(ze);
+ int unixMode = ze.getUnixMode();
+ if (zfs.hasFileModeBeenSet()
+ || ((unixMode == 0
+ || unixMode == UnixStat.FILE_FLAG)
+ && !preserve0Permissions)) {
+ unixMode = fileMode;
+ }
zipFile(is, zOut, prefix + name,
ze.getTime(), zfs.getSrc(getProject()),
- zfs.hasFileModeBeenSet() ? fileMode
- : ze.getUnixMode());
+ unixMode);
} finally {
doCompress = oldCompress;
FileUtils.close(is);
diff --git a/src/main/org/apache/tools/zip/ZipEntry.java b/src/main/org/apache/tools/zip/ZipEntry.java
index 5bceee0fd..4ea215bd6 100644
--- a/src/main/org/apache/tools/zip/ZipEntry.java
+++ b/src/main/org/apache/tools/zip/ZipEntry.java
@@ -28,8 +28,8 @@ import java.util.zip.ZipException;
*/
public class ZipEntry extends java.util.zip.ZipEntry implements Cloneable {
- private static final int PLATFORM_UNIX = 3;
- private static final int PLATFORM_FAT = 0;
+ public static final int PLATFORM_UNIX = 3;
+ public static final int PLATFORM_FAT = 0;
private static final int SHORT_MASK = 0xFFFF;
private static final int SHORT_SHIFT = 16;
@@ -145,7 +145,7 @@ public class ZipEntry extends java.util.zip.ZipEntry implements Cloneable {
*/
public void setUnixMode(int mode) {
// CheckStyle:MagicNumberCheck OFF - no point
- setExternalAttributes((mode << 16)
+ setExternalAttributes((mode << SHORT_SHIFT)
// MS-DOS read-only attribute
| ((mode & 0200) == 0 ? 1 : 0)
// MS-DOS directory flag
@@ -160,15 +160,16 @@ public class ZipEntry extends java.util.zip.ZipEntry implements Cloneable {
* @since Ant 1.6
*/
public int getUnixMode() {
- return (int) ((getExternalAttributes() >> SHORT_SHIFT) & SHORT_MASK);
+ return platform != PLATFORM_UNIX ? 0 :
+ (int) ((getExternalAttributes() >> SHORT_SHIFT) & SHORT_MASK);
}
/**
* Platform specification to put into the "version made
* by" part of the central file header.
*
- * @return 0 (MS-DOS FAT) unless {@link #setUnixMode setUnixMode}
- * has been called, in which case 3 (Unix) will be returned.
+ * @return PLATFORM_FAT unless {@link #setUnixMode setUnixMode}
+ * has been called, in which case PLATORM_UNIX will be returned.
*
* @since Ant 1.5.2
*/
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/ZipTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/ZipTest.java
index e44ce9053..0fc32e658 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/ZipTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/ZipTest.java
@@ -188,4 +188,35 @@ public class ZipTest extends BuildFileTest {
}
}
}
+
+ public void testRewriteZeroPermissions() throws IOException {
+ executeTarget("rewriteZeroPermissions");
+ org.apache.tools.zip.ZipFile zf = null;
+ try {
+ zf = new org.apache.tools.zip.ZipFile(getProject()
+ .resolveFile("test3.zip"));
+ org.apache.tools.zip.ZipEntry ze = zf.getEntry("testdir/test.txt");
+ assertEquals(UnixStat.FILE_FLAG | 0644, ze.getUnixMode());
+ } finally {
+ if (zf != null) {
+ zf.close();
+ }
+ }
+ }
+
+ public void testAcceptZeroPermissions() throws IOException {
+ executeTarget("acceptZeroPermissions");
+ org.apache.tools.zip.ZipFile zf = null;
+ try {
+ zf = new org.apache.tools.zip.ZipFile(getProject()
+ .resolveFile("test3.zip"));
+ org.apache.tools.zip.ZipEntry ze = zf.getEntry("testdir/test.txt");
+ assertEquals(0000, ze.getUnixMode());
+ } finally {
+ if (zf != null) {
+ zf.close();
+ }
+ }
+ }
+
}