git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@677597 13f79535-47bb-0310-9956-ffa450edef68master
@@ -63,6 +63,20 @@ Changes that could break older environments: | |||||
set failOnEmptyArchive to false to restore the old behavior. | set failOnEmptyArchive to false to restore the old behavior. | ||||
Bugzilla report 35000. | Bugzilla report 35000. | ||||
* Ant's <zip> 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 <zip> family of tasks has a new attribute preservce0permissions | |||||
that can be set to restore the old behavior. | |||||
Bugzilla Report 42122. | |||||
Fixed bugs: | Fixed bugs: | ||||
----------- | ----------- | ||||
@@ -185,6 +185,18 @@ to a value other than its default, <code>"add"</code>.</b></p> | |||||
(maximum compression/slowest). <em>Since Ant 1.7</em></td> | (maximum compression/slowest). <em>Since Ant 1.7</em></td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">preserve0permissions</td> | |||||
<td valign="top">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.<br/> | |||||
Set this attribute to true if you really want to preserve the | |||||
original permission field.<em>since Ant 1.8.0</em> | |||||
</td> | |||||
<td valign="top" align="center">No, default is false</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Nested elements</h3> | <h3>Nested elements</h3> | ||||
@@ -239,6 +239,18 @@ to a value other than its default, <code>"add"</code>.</b></p> | |||||
<em>Since Ant 1.7.1</em></td> | <em>Since Ant 1.7.1</em></td> | ||||
<td valign="top" align="center">No, defaults to <tt>ignore</tt>. </td> | <td valign="top" align="center">No, defaults to <tt>ignore</tt>. </td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">preserve0permissions</td> | |||||
<td valign="top">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.<br/> | |||||
Set this attribute to true if you really want to preserve the | |||||
original permission field.<em>since Ant 1.8.0</em> | |||||
</td> | |||||
<td valign="top" align="center">No, default is false</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Nested elements</h3> | <h3>Nested elements</h3> | ||||
@@ -202,6 +202,18 @@ to a value other than its default, <code>"add"</code>.</b></p> | |||||
(maximum compression/slowest). <em>Since Ant 1.7</em></td> | (maximum compression/slowest). <em>Since Ant 1.7</em></td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">preserve0permissions</td> | |||||
<td valign="top">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.<br/> | |||||
Set this attribute to true if you really want to preserve the | |||||
original permission field.<em>since Ant 1.8.0</em> | |||||
</td> | |||||
<td valign="top" align="center">No, default is false</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Nested elements</h3> | <h3>Nested elements</h3> | ||||
@@ -229,6 +229,18 @@ archive.</p> | |||||
(maximum compression/slowest). <em>Since Ant 1.7</em></td> | (maximum compression/slowest). <em>Since Ant 1.7</em></td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">preserve0permissions</td> | |||||
<td valign="top">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.<br/> | |||||
Set this attribute to true if you really want to preserve the | |||||
original permission field.<em>since Ant 1.8.0</em> | |||||
</td> | |||||
<td valign="top" align="center">No, default is false</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
@@ -248,6 +248,18 @@ | |||||
</zip> | </zip> | ||||
</target> | </target> | ||||
<target name="rewriteZeroPermissions"> | |||||
<zip destfile="test3.zip"> | |||||
<zipfileset src="nopermissions.zip"/> | |||||
</zip> | |||||
</target> | |||||
<target name="acceptZeroPermissions"> | |||||
<zip destfile="test3.zip" preserve0permissions="true"> | |||||
<zipfileset src="nopermissions.zip"/> | |||||
</zip> | |||||
</target> | |||||
<target name="cleanup"> | <target name="cleanup"> | ||||
<delete file="testLevel.zip"/> | <delete file="testLevel.zip"/> | ||||
<delete file="test3.zip"/> | <delete file="test3.zip"/> | ||||
@@ -53,6 +53,7 @@ import org.apache.tools.ant.util.GlobPatternMapper; | |||||
import org.apache.tools.ant.util.IdentityMapper; | import org.apache.tools.ant.util.IdentityMapper; | ||||
import org.apache.tools.ant.util.MergingMapper; | import org.apache.tools.ant.util.MergingMapper; | ||||
import org.apache.tools.ant.util.ResourceUtils; | import org.apache.tools.ant.util.ResourceUtils; | ||||
import org.apache.tools.zip.UnixStat; | |||||
import org.apache.tools.zip.ZipEntry; | import org.apache.tools.zip.ZipEntry; | ||||
import org.apache.tools.zip.ZipExtraField; | import org.apache.tools.zip.ZipExtraField; | ||||
import org.apache.tools.zip.ZipFile; | import org.apache.tools.zip.ZipFile; | ||||
@@ -139,6 +140,12 @@ public class Zip extends MatchingTask { | |||||
private int level = ZipOutputStream.DEFAULT_COMPRESSION; | 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 | * This is the name/location of where to | ||||
* create the .zip file. | * create the .zip file. | ||||
@@ -401,6 +408,22 @@ public class Zip extends MatchingTask { | |||||
roundUp = r; | 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 | * validate and build | ||||
* @throws BuildException on error | * @throws BuildException on error | ||||
@@ -774,8 +797,13 @@ public class Zip extends MatchingTask { | |||||
} | } | ||||
if (zf != null) { | if (zf != null) { | ||||
ZipEntry ze = zf.getEntry(resources[i].getName()); | 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, | addParentDirs(base, name, zOut, prefix, | ||||
ze.getUnixMode()); | |||||
unixMode); | |||||
} else { | } else { | ||||
ArchiveResource tr = (ArchiveResource) resources[i]; | ArchiveResource tr = (ArchiveResource) resources[i]; | ||||
addParentDirs(base, name, zOut, prefix, | addParentDirs(base, name, zOut, prefix, | ||||
@@ -802,10 +830,16 @@ public class Zip extends MatchingTask { | |||||
InputStream is = null; | InputStream is = null; | ||||
try { | try { | ||||
is = zf.getInputStream(ze); | 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, | zipFile(is, zOut, prefix + name, | ||||
ze.getTime(), zfs.getSrc(getProject()), | ze.getTime(), zfs.getSrc(getProject()), | ||||
zfs.hasFileModeBeenSet() ? fileMode | |||||
: ze.getUnixMode()); | |||||
unixMode); | |||||
} finally { | } finally { | ||||
doCompress = oldCompress; | doCompress = oldCompress; | ||||
FileUtils.close(is); | FileUtils.close(is); | ||||
@@ -28,8 +28,8 @@ import java.util.zip.ZipException; | |||||
*/ | */ | ||||
public class ZipEntry extends java.util.zip.ZipEntry implements Cloneable { | 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_MASK = 0xFFFF; | ||||
private static final int SHORT_SHIFT = 16; | 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) { | public void setUnixMode(int mode) { | ||||
// CheckStyle:MagicNumberCheck OFF - no point | // CheckStyle:MagicNumberCheck OFF - no point | ||||
setExternalAttributes((mode << 16) | |||||
setExternalAttributes((mode << SHORT_SHIFT) | |||||
// MS-DOS read-only attribute | // MS-DOS read-only attribute | ||||
| ((mode & 0200) == 0 ? 1 : 0) | | ((mode & 0200) == 0 ? 1 : 0) | ||||
// MS-DOS directory flag | // MS-DOS directory flag | ||||
@@ -160,15 +160,16 @@ public class ZipEntry extends java.util.zip.ZipEntry implements Cloneable { | |||||
* @since Ant 1.6 | * @since Ant 1.6 | ||||
*/ | */ | ||||
public int getUnixMode() { | 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 | * Platform specification to put into the "version made | ||||
* by" part of the central file header. | * 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 | * @since Ant 1.5.2 | ||||
*/ | */ | ||||
@@ -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(); | |||||
} | |||||
} | |||||
} | |||||
} | } |