Info-Zip way. PR: 6492 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@273629 13f79535-47bb-0310-9956-ffa450edef68master
@@ -132,6 +132,9 @@ Other changes: | |||||
* <tarfileset> has a new dirmode attribute to specify the permissions | * <tarfileset> has a new dirmode attribute to specify the permissions | ||||
for directories. | for directories. | ||||
* <zip> can now store Unix permissions in a way that can be | |||||
reconstructed by Info-Zip's unzip command. | |||||
Changes from Ant 1.5.1Beta1 to 1.5.1 | Changes from Ant 1.5.1Beta1 to 1.5.1 | ||||
==================================== | ==================================== | ||||
@@ -1183,9 +1183,21 @@ | |||||
<antcall inheritAll="false" target="internal_dist"> | <antcall inheritAll="false" target="internal_dist"> | ||||
<param name="dist.dir" value="${dist.name}"/> | <param name="dist.dir" value="${dist.name}"/> | ||||
</antcall> | </antcall> | ||||
<zip destfile="${dist.base}/bin/${dist.name}-bin.zip" | |||||
basedir="${dist.name}/.." | |||||
includes="${dist.name}/**"/> | |||||
<zip destfile="${dist.base}/bin/${dist.name}-bin.zip"> | |||||
<zipfileset dir="${dist.name}/.." filemode="755"> | |||||
<include name="${dist.name}/bin/ant"/> | |||||
<include name="${dist.name}/bin/antRun"/> | |||||
<include name="${dist.name}/bin/*.pl"/> | |||||
<include name="${dist.name}/bin/*.py"/> | |||||
</zipfileset> | |||||
<fileset dir="${dist.name}/.."> | |||||
<include name="${dist.name}/**"/> | |||||
<exclude name="${dist.name}/bin/ant"/> | |||||
<exclude name="${dist.name}/bin/antRun"/> | |||||
<exclude name="${dist.name}/bin/*.pl"/> | |||||
<exclude name="${dist.name}/bin/*.py"/> | |||||
</fileset> | |||||
</zip> | |||||
<tar longfile="gnu" | <tar longfile="gnu" | ||||
destfile="${dist.base}/bin/${dist.name}-bin.tar"> | destfile="${dist.base}/bin/${dist.name}-bin.tar"> | ||||
<tarfileset dir="${dist.name}/.." mode="755" username="ant" group="ant"> | <tarfileset dir="${dist.name}/.." mode="755" username="ant" group="ant"> | ||||
@@ -1219,9 +1231,17 @@ | |||||
<antcall inheritAll="false" target="src-dist"> | <antcall inheritAll="false" target="src-dist"> | ||||
<param name="src.dist.dir" value="${dist.name}"/> | <param name="src.dist.dir" value="${dist.name}"/> | ||||
</antcall> | </antcall> | ||||
<zip destfile="${dist.base}/src/${dist.name}-src.zip" | |||||
basedir="${dist.name}/.." | |||||
includes="${dist.name}/**"/> | |||||
<zip destfile="${dist.base}/src/${dist.name}-src.zip"> | |||||
<zipfileset dir="${dist.name}/.." filemode="755"> | |||||
<include name="${dist.name}/bootstrap.sh"/> | |||||
<include name="${dist.name}/build.sh"/> | |||||
</zipfileset> | |||||
<fileset dir="${dist.name}/.."> | |||||
<include name="${dist.name}/**"/> | |||||
<exclude name="${dist.name}/bootstrap.sh"/> | |||||
<exclude name="${dist.name}/build.sh"/> | |||||
</fileset> | |||||
</zip> | |||||
<tar longfile="gnu" | <tar longfile="gnu" | ||||
destfile="${dist.base}/src/${dist.name}-src.tar" > | destfile="${dist.base}/src/${dist.name}-src.tar" > | ||||
<tarfileset dir="${dist.name}/.." mode="755" username="ant" group="ant"> | <tarfileset dir="${dist.name}/.." mode="755" username="ant" group="ant"> | ||||
@@ -52,6 +52,15 @@ but causes problems if you try to open them from within Java and your | |||||
filenames contain non US-ASCII characters. Use the encoding attribute | filenames contain non US-ASCII characters. Use the encoding attribute | ||||
and set it to UTF8 to create zip files that can safely be read by | and set it to UTF8 to create zip files that can safely be read by | ||||
Java.</p> | Java.</p> | ||||
<p>Starting with Ant 1.6, <zip> can store Unix permissions | |||||
inside the archive (see description of the filemode and dirmode | |||||
attributes for <a href="#zipfileset"><zipfileset></a>). | |||||
Unfortunately there is no portable way to store these permissions. | |||||
Ant uses the algorithm used by <a href="http://www.info-zip.org">Info-Zip's</a> | |||||
implementation of the zip and unzip commands - these are the default | |||||
versions of zip and unzip for many Unix and Unix-like systems.</p> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -144,15 +153,64 @@ Java.</p> | |||||
<p>The zip task supports any number of nested <a | <p>The zip task supports any number of nested <a | ||||
href="../CoreTypes/fileset.html"><code><fileset></code></a> elements to specify | href="../CoreTypes/fileset.html"><code><fileset></code></a> elements to specify | ||||
the files to be included in the archive.</p> | the files to be included in the archive.</p> | ||||
<h4>zipfileset</h4> | |||||
<p>A <code><zipfileset></code> has three additional attributes: <i>prefix</i>, <i>fullpath</i>, and <i>src</i>. The | |||||
<i>prefix</i> and <i>fullpath</i> attributes modify the location of the files when they are placed | |||||
inside the archive. If the <i>prefix</i> attribute is set, all files in the fileset are prefixed | |||||
with that path in the archive. If the <i>fullpath</i> attribute is set, the file described by the fileset is placed at that | |||||
exact location in the archive. (The <i>fullpath</i> attribute can only be set for filesets that represent a single file. The <i>prefix</i> and <i>fullpath</i> attributes cannot both be set on the same fileset.) The <i>src</i> attribute | |||||
may be used in place of the <i>dir</i> attribute to specify a zip file whose | |||||
contents will be extracted and included in the archive. As with directories, include and exclude patterns may be used to specify a subset of the zip file | |||||
for inclusion in the archive.</p> | |||||
<h4><a name="zipfileset">zipfileset</a></h4> | |||||
<p>A <code><zipfileset></code> is a special form of a | |||||
<code><fileset></code> that adds some extra functionality. It | |||||
supports all attributes of <code><fileset></code> in addition to | |||||
those listed below.</p> | |||||
<h3>Parameters</h3> | |||||
<table border="1" cellpadding="2" cellspacing="0"> | |||||
<tr> | |||||
<td valign="top"><b>Attribute</b></td> | |||||
<td valign="top"><b>Description</b></td> | |||||
<td valign="top" align="center"><b>Required</b></td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">prefix</td> | |||||
<td valign="top">all files in the fileset are prefixed with that | |||||
path in the archive.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">fullpath</td> | |||||
<td valign="top">the file described by the fileset is placed at | |||||
that exact location in the archive.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">src</td> | |||||
<td valign="top">may be used in place of the <i>dir</i> attribute | |||||
to specify a zip file whose contents will be extracted and | |||||
included in the archive.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">filemode</td> | |||||
<td valign="top">A 3 digit octal string, specify the user, group | |||||
and other modes in the standard Unix fashion. Only applies to | |||||
plain files. Default is 644. <em>since Ant 1.6</em>.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">dirmode</td> | |||||
<td valign="top">A 3 digit octal string, specify the user, group | |||||
and other modes in the standard Unix fashion. Only applies to | |||||
directories. Default is 755. <em>since Ant 1.6</em>.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
</table> | |||||
<p>The <i>fullpath</i> attribute can only be set for filesets that | |||||
represent a single file. The <i>prefix</i> and <i>fullpath</i> | |||||
attributes cannot both be set on the same fileset.</p> | |||||
<p>When using the <i>src</i> attribute, include and exclude patterns | |||||
may be used to specify a subset of the zip file for inclusion in the | |||||
archive as with the <i>dir</i> attribute.</p> | |||||
<h4>zipgroupfileset</h4> | <h4>zipgroupfileset</h4> | ||||
<p>A <code><zipgroupfileset></code> allows for multiple zip files to be | <p>A <code><zipgroupfileset></code> allows for multiple zip files to be | ||||
merged into the archive. Each file found in this fileset is added to the archive | merged into the archive. Each file found in this fileset is added to the archive | ||||
@@ -134,7 +134,8 @@ public class Ear extends Jar { | |||||
super.initZipOutputStream(zOut); | super.initZipOutputStream(zOut); | ||||
} | } | ||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath) | |||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath, | |||||
int mode) | |||||
throws IOException { | throws IOException { | ||||
// If the file being added is META-INF/application.xml, we | // If the file being added is META-INF/application.xml, we | ||||
// warn if it's not the one specified in the "appxml" | // warn if it's not the one specified in the "appxml" | ||||
@@ -150,11 +151,11 @@ public class Ear extends Jar { | |||||
+ " be ignored (please use appxml attribute to " | + " be ignored (please use appxml attribute to " | ||||
+ archiveType + " task)", Project.MSG_WARN); | + archiveType + " task)", Project.MSG_WARN); | ||||
} else { | } else { | ||||
super.zipFile(file, zOut, vPath); | |||||
super.zipFile(file, zOut, vPath, mode); | |||||
descriptorAdded = true; | descriptorAdded = true; | ||||
} | } | ||||
} else { | } else { | ||||
super.zipFile(file, zOut, vPath); | |||||
super.zipFile(file, zOut, vPath, mode); | |||||
} | } | ||||
} | } | ||||
@@ -314,7 +314,7 @@ public class Jar extends Zip { | |||||
Project.MSG_WARN); | Project.MSG_WARN); | ||||
} | } | ||||
zipDir(null, zOut, "META-INF/"); | |||||
zipDir(null, zOut, "META-INF/", ZipFileSet.DEFAULT_DIR_MODE); | |||||
// time to write the manifest | // time to write the manifest | ||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||||
PrintWriter writer = new PrintWriter(baos); | PrintWriter writer = new PrintWriter(baos); | ||||
@@ -324,7 +324,8 @@ public class Jar extends Zip { | |||||
ByteArrayInputStream bais = | ByteArrayInputStream bais = | ||||
new ByteArrayInputStream(baos.toByteArray()); | new ByteArrayInputStream(baos.toByteArray()); | ||||
super.zipFile(bais, zOut, "META-INF/MANIFEST.MF", | super.zipFile(bais, zOut, "META-INF/MANIFEST.MF", | ||||
System.currentTimeMillis(), null); | |||||
System.currentTimeMillis(), null, | |||||
ZipFileSet.DEFAULT_FILE_MODE); | |||||
super.initZipOutputStream(zOut); | super.initZipOutputStream(zOut); | ||||
} | } | ||||
@@ -387,20 +388,22 @@ public class Jar extends Zip { | |||||
writer.flush(); | writer.flush(); | ||||
ByteArrayInputStream bais = | ByteArrayInputStream bais = | ||||
new ByteArrayInputStream(baos.toByteArray()); | new ByteArrayInputStream(baos.toByteArray()); | ||||
super.zipFile(bais, zOut, INDEX_NAME, System.currentTimeMillis(), null); | |||||
super.zipFile(bais, zOut, INDEX_NAME, System.currentTimeMillis(), null, | |||||
ZipFileSet.DEFAULT_FILE_MODE); | |||||
} | } | ||||
/** | /** | ||||
* Overriden from Zip class to deal with manifests | * Overriden from Zip class to deal with manifests | ||||
*/ | */ | ||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath) | |||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath, | |||||
int mode) | |||||
throws IOException { | throws IOException { | ||||
if ("META-INF/MANIFEST.MF".equalsIgnoreCase(vPath)) { | if ("META-INF/MANIFEST.MF".equalsIgnoreCase(vPath)) { | ||||
if (! doubleFilePass || (doubleFilePass && skipWriting)) { | if (! doubleFilePass || (doubleFilePass && skipWriting)) { | ||||
filesetManifest(file, null); | filesetManifest(file, null); | ||||
} | } | ||||
} else { | } else { | ||||
super.zipFile(file, zOut, vPath); | |||||
super.zipFile(file, zOut, vPath, mode); | |||||
} | } | ||||
} | } | ||||
@@ -408,14 +411,14 @@ public class Jar extends Zip { | |||||
* Overriden from Zip class to deal with manifests | * Overriden from Zip class to deal with manifests | ||||
*/ | */ | ||||
protected void zipFile(InputStream is, ZipOutputStream zOut, String vPath, | protected void zipFile(InputStream is, ZipOutputStream zOut, String vPath, | ||||
long lastModified, File file) | |||||
long lastModified, File file, int mode) | |||||
throws IOException { | throws IOException { | ||||
if ("META-INF/MANIFEST.MF".equalsIgnoreCase(vPath)) { | if ("META-INF/MANIFEST.MF".equalsIgnoreCase(vPath)) { | ||||
if (! doubleFilePass || (doubleFilePass && skipWriting)) { | if (! doubleFilePass || (doubleFilePass && skipWriting)) { | ||||
filesetManifest(file, is); | filesetManifest(file, is); | ||||
} | } | ||||
} else { | } else { | ||||
super.zipFile(is, zOut, vPath, lastModified, null); | |||||
super.zipFile(is, zOut, vPath, lastModified, null, mode); | |||||
} | } | ||||
} | } | ||||
@@ -172,7 +172,8 @@ public class War extends Jar { | |||||
/** | /** | ||||
* add another file to the stream | * add another file to the stream | ||||
*/ | */ | ||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath) | |||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath, | |||||
int mode) | |||||
throws IOException { | throws IOException { | ||||
// If the file being added is WEB-INF/web.xml, we warn if it's | // If the file being added is WEB-INF/web.xml, we warn if it's | ||||
// not the one specified in the "webxml" attribute - or if | // not the one specified in the "webxml" attribute - or if | ||||
@@ -187,11 +188,11 @@ public class War extends Jar { | |||||
+ "(please use webxml attribute to " | + "(please use webxml attribute to " | ||||
+ archiveType + " task)", Project.MSG_WARN); | + archiveType + " task)", Project.MSG_WARN); | ||||
} else { | } else { | ||||
super.zipFile(file, zOut, vPath); | |||||
super.zipFile(file, zOut, vPath, mode); | |||||
descriptorAdded = true; | descriptorAdded = true; | ||||
} | } | ||||
} else { | } else { | ||||
super.zipFile(file, zOut, vPath); | |||||
super.zipFile(file, zOut, vPath, mode); | |||||
} | } | ||||
} | } | ||||
@@ -388,7 +388,9 @@ public class Zip extends MatchingTask { | |||||
// Add the implicit fileset to the archive. | // Add the implicit fileset to the archive. | ||||
if (baseDir != null) { | if (baseDir != null) { | ||||
addFiles(getDirectoryScanner(baseDir), zOut, "", ""); | |||||
addFiles(getDirectoryScanner(baseDir), zOut, "", "", | |||||
ZipFileSet.DEFAULT_DIR_MODE, | |||||
ZipFileSet.DEFAULT_FILE_MODE); | |||||
} | } | ||||
// Add the explicit filesets to the archive. | // Add the explicit filesets to the archive. | ||||
addFiles(filesets, zOut); | addFiles(filesets, zOut); | ||||
@@ -473,10 +475,28 @@ public class Zip extends MatchingTask { | |||||
* prependig the given prefix to each filename. | * prependig the given prefix to each filename. | ||||
* | * | ||||
* <p>Ensure parent directories have been added as well. | * <p>Ensure parent directories have been added as well. | ||||
* | |||||
* @deprecated use six-arg version instead. | |||||
*/ | */ | ||||
protected void addFiles(FileScanner scanner, ZipOutputStream zOut, | protected void addFiles(FileScanner scanner, ZipOutputStream zOut, | ||||
String prefix, String fullpath) | String prefix, String fullpath) | ||||
throws IOException { | throws IOException { | ||||
addFiles(scanner, zOut, prefix, fullpath, ZipFileSet.DEFAULT_DIR_MODE, | |||||
ZipFileSet.DEFAULT_FILE_MODE); | |||||
} | |||||
/** | |||||
* Add all files of the given FileScanner to the ZipOutputStream | |||||
* prependig the given prefix to each filename. | |||||
* | |||||
* <p>Ensure parent directories have been added as well. | |||||
* | |||||
* @since Ant 1.6 | |||||
*/ | |||||
protected void addFiles(FileScanner scanner, ZipOutputStream zOut, | |||||
String prefix, String fullpath, int dirMode, | |||||
int fileMode) | |||||
throws IOException { | |||||
if (prefix.length() > 0 && fullpath.length() > 0) { | if (prefix.length() > 0 && fullpath.length() > 0) { | ||||
throw new BuildException("Both prefix and fullpath attributes must" | throw new BuildException("Both prefix and fullpath attributes must" | ||||
@@ -500,7 +520,7 @@ public class Zip extends MatchingTask { | |||||
if (!name.endsWith("/")) { | if (!name.endsWith("/")) { | ||||
name += "/"; | name += "/"; | ||||
} | } | ||||
addParentDirs(thisBaseDir, name, zOut, prefix); | |||||
addParentDirs(thisBaseDir, name, zOut, prefix, dirMode); | |||||
} | } | ||||
// files that matched include patterns | // files that matched include patterns | ||||
@@ -514,13 +534,13 @@ public class Zip extends MatchingTask { | |||||
File f = new File(thisBaseDir, files[i]); | File f = new File(thisBaseDir, files[i]); | ||||
if (fullpath.length() > 0) { | if (fullpath.length() > 0) { | ||||
// Add this file at the specified location. | // Add this file at the specified location. | ||||
addParentDirs(null, fullpath, zOut, ""); | |||||
zipFile(f, zOut, fullpath); | |||||
addParentDirs(null, fullpath, zOut, "", dirMode); | |||||
zipFile(f, zOut, fullpath, fileMode); | |||||
} else { | } else { | ||||
// Add this file with the specified prefix. | // Add this file with the specified prefix. | ||||
String name = files[i].replace(File.separatorChar, '/'); | String name = files[i].replace(File.separatorChar, '/'); | ||||
addParentDirs(thisBaseDir, name, zOut, prefix); | |||||
zipFile(f, zOut, prefix + name); | |||||
addParentDirs(thisBaseDir, name, zOut, prefix, dirMode); | |||||
zipFile(f, zOut, prefix + name, fileMode); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -550,13 +570,16 @@ public class Zip extends MatchingTask { | |||||
String vPath = entry.getName(); | String vPath = entry.getName(); | ||||
if (zipScanner.match(vPath)) { | if (zipScanner.match(vPath)) { | ||||
if (fullpath.length() > 0) { | if (fullpath.length() > 0) { | ||||
addParentDirs(null, fullpath, zOut, ""); | |||||
zipFile(in, zOut, fullpath, entry.getTime(), zipSrc); | |||||
addParentDirs(null, fullpath, zOut, "", | |||||
fs.getDirMode()); | |||||
zipFile(in, zOut, fullpath, entry.getTime(), zipSrc, | |||||
fs.getFileMode()); | |||||
} else { | } else { | ||||
addParentDirs(null, vPath, zOut, prefix); | |||||
addParentDirs(null, vPath, zOut, prefix, | |||||
fs.getDirMode()); | |||||
if (!entry.isDirectory()) { | if (!entry.isDirectory()) { | ||||
zipFile(in, zOut, prefix + vPath, entry.getTime(), | zipFile(in, zOut, prefix + vPath, entry.getTime(), | ||||
zipSrc); | |||||
zipSrc, fs.getFileMode()); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -701,8 +724,20 @@ public class Zip extends MatchingTask { | |||||
return result; | return result; | ||||
} | } | ||||
/** | |||||
* @deprecated use four-arg version instead. | |||||
*/ | |||||
protected void zipDir(File dir, ZipOutputStream zOut, String vPath) | protected void zipDir(File dir, ZipOutputStream zOut, String vPath) | ||||
throws IOException { | throws IOException { | ||||
zipDir(dir, zOut, vPath, ZipFileSet.DEFAULT_DIR_MODE); | |||||
} | |||||
/** | |||||
* @since Ant 1.6 | |||||
*/ | |||||
protected void zipDir(File dir, ZipOutputStream zOut, String vPath, | |||||
int mode) | |||||
throws IOException { | |||||
if (addedDirs.get(vPath) != null) { | if (addedDirs.get(vPath) != null) { | ||||
// don't add directories we've already added. | // don't add directories we've already added. | ||||
// no warning if we try, it is harmless in and of itself | // no warning if we try, it is harmless in and of itself | ||||
@@ -723,17 +758,28 @@ public class Zip extends MatchingTask { | |||||
ze.setMethod (ZipEntry.STORED); | ze.setMethod (ZipEntry.STORED); | ||||
// This is faintly ridiculous: | // This is faintly ridiculous: | ||||
ze.setCrc (EMPTY_CRC); | ze.setCrc (EMPTY_CRC); | ||||
// this is 040775 | MS-DOS directory flag in reverse byte order | |||||
ze.setExternalAttributes(0x41FD0010L); | |||||
ze.setUnixMode(mode); | |||||
zOut.putNextEntry (ze); | zOut.putNextEntry (ze); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* @deprecated use six-arg version instead. | |||||
*/ | |||||
protected void zipFile(InputStream in, ZipOutputStream zOut, String vPath, | protected void zipFile(InputStream in, ZipOutputStream zOut, String vPath, | ||||
long lastModified, File file) | long lastModified, File file) | ||||
throws IOException { | throws IOException { | ||||
zipFile(in, zOut, vPath, lastModified, file, | |||||
ZipFileSet.DEFAULT_FILE_MODE); | |||||
} | |||||
/** | |||||
* @since Ant 1.6 | |||||
*/ | |||||
protected void zipFile(InputStream in, ZipOutputStream zOut, String vPath, | |||||
long lastModified, File file, int mode) | |||||
throws IOException { | |||||
if (entries.contains(vPath)) { | if (entries.contains(vPath)) { | ||||
if (duplicate.equals("preserve")) { | if (duplicate.equals("preserve")) { | ||||
@@ -759,14 +805,15 @@ public class Zip extends MatchingTask { | |||||
ze.setTime(lastModified); | ze.setTime(lastModified); | ||||
/* | /* | ||||
* XXX ZipOutputStream.putEntry expects the ZipEntry to know its | |||||
* size and the CRC sum before you start writing the data when using | |||||
* STORED mode. | |||||
* ZipOutputStream.putNextEntry expects the ZipEntry to | |||||
* know its size and the CRC sum before you start writing | |||||
* the data when using STORED mode. | |||||
* | * | ||||
* This forces us to process the data twice. | * This forces us to process the data twice. | ||||
* | * | ||||
* I couldn't find any documentation on this, just found out by try | |||||
* and error. | |||||
* In DEFLATED mode, it will take advantage of a Zip | |||||
* Version 2 feature where size can be stored after the | |||||
* data (as the data itself signals end of data). | |||||
*/ | */ | ||||
if (!doCompress) { | if (!doCompress) { | ||||
long size = 0; | long size = 0; | ||||
@@ -800,6 +847,7 @@ public class Zip extends MatchingTask { | |||||
ze.setCrc(cal.getValue()); | ze.setCrc(cal.getValue()); | ||||
} | } | ||||
ze.setUnixMode(mode); | |||||
zOut.putNextEntry(ze); | zOut.putNextEntry(ze); | ||||
byte[] buffer = new byte[8 * 1024]; | byte[] buffer = new byte[8 * 1024]; | ||||
@@ -814,8 +862,20 @@ public class Zip extends MatchingTask { | |||||
addedFiles.addElement(vPath); | addedFiles.addElement(vPath); | ||||
} | } | ||||
/** | |||||
* @deprecated use six-arg version instead. | |||||
*/ | |||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath) | protected void zipFile(File file, ZipOutputStream zOut, String vPath) | ||||
throws IOException { | throws IOException { | ||||
zipFile(file, zOut, vPath, ZipFileSet.DEFAULT_FILE_MODE); | |||||
} | |||||
/** | |||||
* @since Ant 1.6 | |||||
*/ | |||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath, | |||||
int mode) | |||||
throws IOException { | |||||
if (file.equals(zipFile)) { | if (file.equals(zipFile)) { | ||||
throw new BuildException("A zip file cannot include itself", | throw new BuildException("A zip file cannot include itself", | ||||
getLocation()); | getLocation()); | ||||
@@ -823,18 +883,31 @@ public class Zip extends MatchingTask { | |||||
FileInputStream fIn = new FileInputStream(file); | FileInputStream fIn = new FileInputStream(file); | ||||
try { | try { | ||||
zipFile(fIn, zOut, vPath, file.lastModified(), null); | |||||
zipFile(fIn, zOut, vPath, file.lastModified(), null, mode); | |||||
} finally { | } finally { | ||||
fIn.close(); | fIn.close(); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Ensure all parent dirs of a given entry have been added. | |||||
* @deprecated use five-arg version instead. | |||||
*/ | */ | ||||
protected void addParentDirs(File baseDir, String entry, | protected void addParentDirs(File baseDir, String entry, | ||||
ZipOutputStream zOut, String prefix) | ZipOutputStream zOut, String prefix) | ||||
throws IOException { | throws IOException { | ||||
addParentDirs(baseDir, entry, zOut, prefix, | |||||
ZipFileSet.DEFAULT_DIR_MODE); | |||||
} | |||||
/** | |||||
* Ensure all parent dirs of a given entry have been added. | |||||
* | |||||
* @since Ant 1.6 | |||||
*/ | |||||
protected void addParentDirs(File baseDir, String entry, | |||||
ZipOutputStream zOut, String prefix, | |||||
int dirMode) | |||||
throws IOException { | |||||
if (!doFilesonly) { | if (!doFilesonly) { | ||||
Stack directories = new Stack(); | Stack directories = new Stack(); | ||||
int slashPos = entry.length(); | int slashPos = entry.length(); | ||||
@@ -855,7 +928,7 @@ public class Zip extends MatchingTask { | |||||
} else { | } else { | ||||
f = new File(dir); | f = new File(dir); | ||||
} | } | ||||
zipDir(f, zOut, prefix + dir); | |||||
zipDir(f, zOut, prefix + dir, dirMode); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -874,10 +947,14 @@ public class Zip extends MatchingTask { | |||||
String prefix = ""; | String prefix = ""; | ||||
String fullpath = ""; | String fullpath = ""; | ||||
int fileMode = ZipFileSet.DEFAULT_FILE_MODE; | |||||
int dirMode = ZipFileSet.DEFAULT_DIR_MODE; | |||||
if (fs instanceof ZipFileSet) { | if (fs instanceof ZipFileSet) { | ||||
ZipFileSet zfs = (ZipFileSet) fs; | ZipFileSet zfs = (ZipFileSet) fs; | ||||
prefix = zfs.getPrefix(); | prefix = zfs.getPrefix(); | ||||
fullpath = zfs.getFullpath(); | fullpath = zfs.getFullpath(); | ||||
fileMode = zfs.getFileMode(); | |||||
dirMode = zfs.getDirMode(); | |||||
} | } | ||||
if (prefix.length() > 0 | if (prefix.length() > 0 | ||||
@@ -889,10 +966,10 @@ public class Zip extends MatchingTask { | |||||
// Need to manually add either fullpath's parent directory, or | // Need to manually add either fullpath's parent directory, or | ||||
// the prefix directory, to the archive. | // the prefix directory, to the archive. | ||||
if (prefix.length() > 0) { | if (prefix.length() > 0) { | ||||
addParentDirs(null, prefix, zOut, ""); | |||||
zipDir(null, zOut, prefix); | |||||
addParentDirs(null, prefix, zOut, "", dirMode); | |||||
zipDir(null, zOut, prefix, dirMode); | |||||
} else if (fullpath.length() > 0) { | } else if (fullpath.length() > 0) { | ||||
addParentDirs(null, fullpath, zOut, ""); | |||||
addParentDirs(null, fullpath, zOut, "", dirMode); | |||||
} | } | ||||
if (fs instanceof ZipFileSet | if (fs instanceof ZipFileSet | ||||
@@ -900,7 +977,7 @@ public class Zip extends MatchingTask { | |||||
addZipEntries((ZipFileSet) fs, ds, zOut, prefix, fullpath); | addZipEntries((ZipFileSet) fs, ds, zOut, prefix, fullpath); | ||||
} else { | } else { | ||||
// Add the fileset. | // Add the fileset. | ||||
addFiles(ds, zOut, prefix, fullpath); | |||||
addFiles(ds, zOut, prefix, fullpath, dirMode, fileMode); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -80,12 +80,28 @@ import org.apache.tools.zip.UnixStat; | |||||
*/ | */ | ||||
public class ZipFileSet extends FileSet { | public class ZipFileSet extends FileSet { | ||||
/** | |||||
* Default value for the dirmode attribute. | |||||
* | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public static final int DEFAULT_DIR_MODE = | |||||
UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM; | |||||
/** | |||||
* Default value for the filemode attribute. | |||||
* | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public static final int DEFAULT_FILE_MODE = | |||||
UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM; | |||||
private File srcFile = null; | private File srcFile = null; | ||||
private String prefix = ""; | private String prefix = ""; | ||||
private String fullpath = ""; | private String fullpath = ""; | ||||
private boolean hasDir = false; | private boolean hasDir = false; | ||||
private int fileMode = UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM; | |||||
private int dirMode = UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM; | |||||
private int fileMode = DEFAULT_FILE_MODE; | |||||
private int dirMode = DEFAULT_DIR_MODE; | |||||
public ZipFileSet() { | public ZipFileSet() { | ||||
super(); | super(); | ||||
@@ -198,6 +198,8 @@ public class ZipEntry extends java.util.zip.ZipEntry { | |||||
*/ | */ | ||||
public void setUnixMode(int mode) { | public void setUnixMode(int mode) { | ||||
setExternalAttributes((mode << 16) | setExternalAttributes((mode << 16) | ||||
// MS-DOS read-only attribute | |||||
| ((mode & 0200) == 0 ? 1 : 0) | |||||
// MS-DOS directory flag | // MS-DOS directory flag | ||||
| (isDirectory() ? 0x10 : 0)); | | (isDirectory() ? 0x10 : 0)); | ||||
platform = PLATFORM_UNIX; | platform = PLATFORM_UNIX; | ||||
@@ -131,12 +131,25 @@ public class ZipEntryTest extends TestCase { | |||||
(ze.getExternalAttributes() >> 16) & 0xFFFF); | (ze.getExternalAttributes() >> 16) & 0xFFFF); | ||||
assertEquals(0, ze.getExternalAttributes() & 0xFFFF); | assertEquals(0, ze.getExternalAttributes() & 0xFFFF); | ||||
ze.setUnixMode(0444); | |||||
assertEquals(3, ze.getPlatform()); | |||||
assertEquals(0444, | |||||
(ze.getExternalAttributes() >> 16) & 0xFFFF); | |||||
assertEquals(1, ze.getExternalAttributes() & 0xFFFF); | |||||
ze = new ZipEntry("foo/"); | ze = new ZipEntry("foo/"); | ||||
assertEquals(0, ze.getPlatform()); | |||||
ze.setUnixMode(0777); | |||||
assertEquals(3, ze.getPlatform()); | |||||
assertEquals(0777, | |||||
(ze.getExternalAttributes() >> 16) & 0xFFFF); | |||||
assertEquals(0x10, ze.getExternalAttributes() & 0xFFFF); | |||||
ze.setUnixMode(0577); | ze.setUnixMode(0577); | ||||
assertEquals(3, ze.getPlatform()); | assertEquals(3, ze.getPlatform()); | ||||
assertEquals(0577, | assertEquals(0577, | ||||
(ze.getExternalAttributes() >> 16) & 0xFFFF); | (ze.getExternalAttributes() >> 16) & 0xFFFF); | ||||
assertEquals(0x10, ze.getExternalAttributes() & 0xFFFF); | |||||
assertEquals(0x11, ze.getExternalAttributes() & 0xFFFF); | |||||
} | } | ||||
} | } |