Bug 42122 - <zipfileset src="some.zip"/> copies the wrong file permission
Summary: <zipfileset src="some.zip"/> copies the wrong file permission
Status: RESOLVED FIXED
Alias: None
Product: Ant
Classification: Unclassified
Component: Core tasks (show other bugs)
Version: 1.7.0
Hardware: Other other
: P2 normal with 1 vote (vote)
Target Milestone: 1.8.0
Assignee: Ant Notifications List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-04-13 19:28 UTC by Kohsuke Kawaguchi
Modified: 2008-07-17 07:48 UTC (History)
2 users (show)



Attachments
use getUnixMode() only when the platform is unix (1.21 KB, patch)
2008-04-09 19:02 UTC, Kostas Georgiou
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kohsuke Kawaguchi 2007-04-13 19:28:53 UTC
Ant apparently uses the "external file attributes" field of the zip file entry
(more specifically it's top 16 bits) for file permission. I couldn't confirm
this in the PKZIP specification at http://www.info-zip.org/pub/infozip/doc/, but
from what I can see from various other unzip implementations (most notably
solaris /bin/unzip), this seems to be a standard practice.

However, apparently not all zip program creates zip files by using these
attributes. I couldn't confirm which program created this one zip file, but I
got one where external file attributes is set to 0. The platform bit is also set
to 0, which indicates that the file permission is not stored in the zip file.

When I use such a zip file as a source of the <zipfileset> to re-zip it into
another zip file, such as:

<zip destfile="foo.zip">
  <zipfileset src="bar.zip"/>
</zip>

in an attempt to copy all entries, Ant internally call into
ZipResource.setEntry(), which does the following:

    private void setEntry(ZipEntry e) {
        if (e == null) {
            setExists(false);
            return;
        }
        setName(e.getName());
        setExists(true);
        setLastModified(e.getTime());
        setDirectory(e.isDirectory());
        setSize(e.getSize());
        setMode(e.getUnixMode());
    }

The problematic bit is the last "setMode(e.getUnixMode())". As I wrote above, my
zip file declares the platform=0, so the unix mode is really not set at all, and
the getUnixMode returns 0. But Ant calls the setMode() method anyway, assuming
that this 0 value is the explicitly set value, which causes:

    public void setMode(int mode) {
        checkAttributesAllowed();
        this.mode = mode;
        modeSet = true;
    }

This eventually causes entries in the created foo.zip to have 000 permission.

I believe the code needs to be changed to:

    if(e.getPlatform()==3) // if platform is UNIX
        setMode(e.getUnixMode());
Comment 1 Kostas Georgiou 2008-04-09 17:21:17 UTC
I get similar problems (mode 000) with something like:

<jar jarfile="${dist.jar}" basedir="${build}">
  <zipgroupfileset dir="${mergedir}" includes="*.jar" />
</jar>

The jar files in ${mergedir} have been created with Sun's jar which doesn't include a unix mode.
Comment 2 Kostas Georgiou 2008-04-09 19:02:20 UTC
Created attachment 21801 [details]
use getUnixMode() only when the platform is unix
Comment 3 Kostas Georgiou 2008-04-09 19:12:59 UTC
The above batch fixes my testcase, since it's on Zip.java it's very likely that it will solve the original problem as well. The original solution didn't work (for my testcase) but it should also be used since it makes sense.
Comment 4 Stefan Bodewig 2008-07-17 07:48:14 UTC
I'm not sure that looking at the platform flag alone was sufficient, so I changed the code to assume a mode of 0000 must be unintentional - unless the user tells Ant it is desired.

subversion revision 677597