Browse Source

Add support for Unix permissions to <zip> and friends, doing it the

Info-Zip way.

PR: 6492


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@273629 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 22 years ago
parent
commit
3255fa8ff4
10 changed files with 250 additions and 56 deletions
  1. +3
    -0
      WHATSNEW
  2. +26
    -6
      build.xml
  3. +67
    -9
      docs/manual/CoreTasks/zip.html
  4. +4
    -3
      src/main/org/apache/tools/ant/taskdefs/Ear.java
  5. +10
    -7
      src/main/org/apache/tools/ant/taskdefs/Jar.java
  6. +4
    -3
      src/main/org/apache/tools/ant/taskdefs/War.java
  7. +102
    -25
      src/main/org/apache/tools/ant/taskdefs/Zip.java
  8. +18
    -2
      src/main/org/apache/tools/ant/types/ZipFileSet.java
  9. +2
    -0
      src/main/org/apache/tools/zip/ZipEntry.java
  10. +14
    -1
      src/testcases/org/apache/tools/zip/ZipEntryTest.java

+ 3
- 0
WHATSNEW View File

@@ -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
==================================== ====================================




+ 26
- 6
build.xml View File

@@ -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">


+ 67
- 9
docs/manual/CoreTasks/zip.html View File

@@ -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, &lt;zip&gt; can store Unix permissions
inside the archive (see description of the filemode and dirmode
attributes for <a href="#zipfileset">&lt;zipfileset&gt;</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>&lt;fileset&gt;</code></a> elements to specify href="../CoreTypes/fileset.html"><code>&lt;fileset&gt;</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>&lt;zipfileset&gt;</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>&lt;zipfileset&gt;</code> is a special form of a
<code>&lt;fileset&gt;</code> that adds some extra functionality. It
supports all attributes of <code>&lt;fileset&gt;</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>&lt;zipgroupfileset&gt;</code> allows for multiple zip files to be <p>A <code>&lt;zipgroupfileset&gt;</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


+ 4
- 3
src/main/org/apache/tools/ant/taskdefs/Ear.java View File

@@ -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);
} }
} }




+ 10
- 7
src/main/org/apache/tools/ant/taskdefs/Jar.java View File

@@ -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);
} }
} }




+ 4
- 3
src/main/org/apache/tools/ant/taskdefs/War.java View File

@@ -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);
} }
} }




+ 102
- 25
src/main/org/apache/tools/ant/taskdefs/Zip.java View File

@@ -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);
} }
} }
} }


+ 18
- 2
src/main/org/apache/tools/ant/types/ZipFileSet.java View File

@@ -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();


+ 2
- 0
src/main/org/apache/tools/zip/ZipEntry.java View File

@@ -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;


+ 14
- 1
src/testcases/org/apache/tools/zip/ZipEntryTest.java View File

@@ -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);
} }


} }

Loading…
Cancel
Save