You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by "Michael Osipov (Jira)" <ji...@apache.org> on 2021/11/18 20:02:00 UTC
[jira] [Comment Edited] (MTOOLCHAINS-39) Can't unzip/unjar maven-toolchain-1.0.jar that is available at Maven Central
[ https://issues.apache.org/jira/browse/MTOOLCHAINS-39?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17446123#comment-17446123 ]
Michael Osipov edited comment on MTOOLCHAINS-39 at 11/18/21, 8:01 PM:
----------------------------------------------------------------------
Well, I can confirm this and thanks to you I learned a bit more about ZIP today. Lets dive into the analysis:
My setup:
{noformat}
osipovmi@deblndw011x:/tmp/maven-toolchains
$ uname -a
FreeBSD deblndw011x.ad001.siemens.net 12.2-STABLE FreeBSD 12.2-STABLE #0: Thu Sep 23 18:58:50 CEST 2021
osipovmi@deblndw011x:/tmp/maven-toolchains
$ which unzip
/usr/bin/unzip
osipovmi@deblndw011x:/tmp/maven-toolchains
$ pkg which /usr/local/bin/zipdetails
/usr/local/bin/zipdetails was installed by package perl5-5.30.3_1
osipovmi@deblndw011x:/tmp/maven-toolchains
$ java -version
openjdk version "1.8.0_302"
OpenJDK Runtime Environment (build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (build 25.302-b08, mixed mode)
{noformat}
Lets unzip first:
{noformat}
$ unzip maven-toolchain-1.0.jar
Archive: maven-toolchain-1.0.jar
extracting: META-INF
extracting: META-INF/MANIFEST.MF
extracting: org
extracting: org/apache
extracting: org/apache/maven
extracting: org/apache/maven/toolchain
extracting: org/apache/maven/toolchain/java
extracting: org/apache/maven/toolchain/java/DefaultJavaToolchainFactory.class
extracting: org/apache/maven/toolchain/java/JavaToolChain.class
extracting: org/apache/maven/toolchain/java/DefaultJavaToolChain.class
extracting: org/apache/maven/toolchain/ToolchainManagerPrivate.class
extracting: org/apache/maven/toolchain/DefaultToolchain.class
extracting: org/apache/maven/toolchain/ToolchainPrivate.class
extracting: org/apache/maven/toolchain/MisconfiguredToolchainException.class
extracting: org/apache/maven/toolchain/ToolchainManager.class
extracting: org/apache/maven/toolchain/ToolchainFactory$1.class
extracting: org/apache/maven/toolchain/model
extracting: org/apache/maven/toolchain/model/ToolchainModel.class
extracting: org/apache/maven/toolchain/model/PersistedToolchains.class
extracting: org/apache/maven/toolchain/model/io
extracting: org/apache/maven/toolchain/model/io/xpp3
extracting: org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Reader.class
extracting: org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Writer.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$ExactMatcher.class
extracting: org/apache/maven/toolchain/Toolchain.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$1.class
extracting: org/apache/maven/toolchain/ToolchainManagerPrivate$1.class
extracting: org/apache/maven/toolchain/DefaultToolchainManager.class
extracting: org/apache/maven/toolchain/ToolchainFactory.class
extracting: org/apache/maven/toolchain/ToolchainManager$1.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$VersionMatcher.class
extracting: org/apache/maven/toolchain/RequirementMatcher.class
extracting: META-INF/plexus
extracting: META-INF/plexus/components.xml
extracting: META-INF/maven
extracting: META-INF/maven/org.apache.maven
extracting: META-INF/maven/org.apache.maven/maven-toolchain
extracting: META-INF/maven/org.apache.maven/maven-toolchain/pom.xml
extracting: META-INF/maven/org.apache.maven/maven-toolchain/pom.properties
osipovmi@deblndw011x:/tmp/maven-toolchains
$ unzip maven-toolchain-2.0.9.jar
Archive: maven-toolchain-2.0.9.jar
creating: META-INF/
extracting: META-INF/MANIFEST.MF
extracting: META-INF/LICENSE
extracting: META-INF/NOTICE
creating: META-INF/plexus/
extracting: META-INF/plexus/components.xml
creating: org/
creating: org/apache/
creating: org/apache/maven/
creating: org/apache/maven/toolchain/
extracting: org/apache/maven/toolchain/DefaultToolchain.class
extracting: org/apache/maven/toolchain/DefaultToolchainManager.class
creating: org/apache/maven/toolchain/java/
extracting: org/apache/maven/toolchain/java/DefaultJavaToolChain.class
extracting: org/apache/maven/toolchain/java/DefaultJavaToolchainFactory.class
extracting: org/apache/maven/toolchain/java/JavaToolChain.class
extracting: org/apache/maven/toolchain/MisconfiguredToolchainException.class
creating: org/apache/maven/toolchain/model/
creating: org/apache/maven/toolchain/model/io/
creating: org/apache/maven/toolchain/model/io/xpp3/
extracting: org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Reader.class
extracting: org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Writer.class
extracting: org/apache/maven/toolchain/model/PersistedToolchains.class
extracting: org/apache/maven/toolchain/model/ToolchainModel.class
extracting: org/apache/maven/toolchain/RequirementMatcher.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$1.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$ExactMatcher.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$VersionMatcher.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory.class
extracting: org/apache/maven/toolchain/Toolchain.class
extracting: org/apache/maven/toolchain/ToolchainFactory$1.class
extracting: org/apache/maven/toolchain/ToolchainFactory.class
extracting: org/apache/maven/toolchain/ToolchainManager$1.class
extracting: org/apache/maven/toolchain/ToolchainManager.class
extracting: org/apache/maven/toolchain/ToolchainManagerPrivate$1.class
extracting: org/apache/maven/toolchain/ToolchainManagerPrivate.class
extracting: org/apache/maven/toolchain/ToolchainPrivate.class
creating: META-INF/maven/
creating: META-INF/maven/org.apache.maven/
creating: META-INF/maven/org.apache.maven/maven-toolchain/
extracting: META-INF/maven/org.apache.maven/maven-toolchain/pom.xml
extracting: META-INF/maven/org.apache.maven/maven-toolchain/pom.properties
{noformat}
You already see that the output is different in 1.0 it is extracting dirs and in 2.0.x is creating them. {{unzip}} handles this case for you.
Where is the difference now?
Spec says:
{quote}
4.4.15 external file attributes: (4 bytes)
The mapping of the external attributes is
host-system dependent (see 'version made by'). For
MS-DOS, the low order byte is the MS-DOS directory
attribute byte. If input came from standard input, this
field is set to zero.
{quote}
Lets check the ZIP details on {{META-INF}} for 1.0:
{noformat}
....
0000 0004 50 4B 03 04 LOCAL HEADER #1 04034B50
0004 0001 14 Extract Zip Spec 14 '2.0'
0005 0001 00 Extract OS 00 'MS-DOS'
0006 0002 08 00 General Purpose Flag 0008
[Bits 1-2] 0 'Normal Compression'
[Bit 3] 1 'Streamed'
0008 0002 08 00 Compression Method 0008 'Deflated'
000A 0004 70 9F 5C 38 Last Mod Time 385C9F70 'Thu Feb 28 19:59:32 2008'
000E 0004 00 00 00 00 CRC 00000000
0012 0004 00 00 00 00 Compressed Length 00000000
0016 0004 00 00 00 00 Uncompressed Length 00000000
001A 0002 08 00 Filename Length 0008
001C 0002 04 00 Extra Length 0004
001E 0008 4D 45 54 41 Filename 'META-INF'
2D 49 4E 46
0026 0002 FE CA Extra ID #0001 CAFE 'Java Executable'
0028 0002 00 00 Length 0000
002A 0002 03 00 PAYLOAD ..
...
7246 0004 50 4B 01 02 CENTRAL HEADER #1 02014B50
724A 0001 14 Created Zip Spec 14 '2.0'
724B 0001 00 Created OS 00 'MS-DOS'
724C 0001 14 Extract Zip Spec 14 '2.0'
724D 0001 00 Extract OS 00 'MS-DOS'
724E 0002 08 00 General Purpose Flag 0008
[Bits 1-2] 0 'Normal Compression'
[Bit 3] 1 'Streamed'
7250 0002 08 00 Compression Method 0008 'Deflated'
7252 0004 70 9F 5C 38 Last Mod Time 385C9F70 'Thu Feb 28 19:59:32 2008'
7256 0004 00 00 00 00 CRC 00000000
725A 0004 02 00 00 00 Compressed Length 00000002
725E 0004 00 00 00 00 Uncompressed Length 00000000
7262 0002 08 00 Filename Length 0008
7264 0002 04 00 Extra Length 0004
7266 0002 00 00 Comment Length 0000
7268 0002 00 00 Disk Start 0000
726A 0002 00 00 Int File Attributes 0000
[Bit 0] 0 'Binary Data'
726C 0004 00 00 00 00 Ext File Attributes 00000000
7270 0004 00 00 00 00 Local Header Offset 00000000
7274 0008 4D 45 54 41 Filename 'META-INF'
2D 49 4E 46
727C 0002 FE CA Extra ID #0001 CAFE 'Java Executable'
727E 0002 00 00 Length 0000
...
{noformat}
Lets check the ZIP details on {{META-INF}} for 2.0.x:
{noformat}
....
0000 0004 50 4B 03 04 LOCAL HEADER #1 04034B50
0004 0001 14 Extract Zip Spec 14 '2.0'
0005 0001 00 Extract OS 00 'MS-DOS'
0006 0002 08 00 General Purpose Flag 0008
[Bits 1-2] 0 'Normal Compression'
[Bit 3] 1 'Streamed'
0008 0002 08 00 Compression Method 0008 'Deflated'
000A 0004 D4 62 87 38 Last Mod Time 388762D4 'Mon Apr 7 12:22:40 2008'
000E 0004 00 00 00 00 CRC 00000000
0012 0004 00 00 00 00 Compressed Length 00000000
0016 0004 00 00 00 00 Uncompressed Length 00000000
001A 0002 09 00 Filename Length 0009
001C 0002 04 00 Extra Length 0004
001E 0009 4D 45 54 41 Filename 'META-INF/'
2D 49 4E 46
2F
0027 0002 FE CA Extra ID #0001 CAFE 'Java Executable'
0029 0002 00 00 Length 0000
002B 0002 03 00 PAYLOAD ..
...
8583 0004 50 4B 01 02 CENTRAL HEADER #1 02014B50
8587 0001 14 Created Zip Spec 14 '2.0'
8588 0001 00 Created OS 00 'MS-DOS'
8589 0001 14 Extract Zip Spec 14 '2.0'
858A 0001 00 Extract OS 00 'MS-DOS'
858B 0002 08 00 General Purpose Flag 0008
[Bits 1-2] 0 'Normal Compression'
[Bit 3] 1 'Streamed'
858D 0002 08 00 Compression Method 0008 'Deflated'
858F 0004 D4 62 87 38 Last Mod Time 388762D4 'Mon Apr 7 12:22:40 2008'
8593 0004 00 00 00 00 CRC 00000000
8597 0004 02 00 00 00 Compressed Length 00000002
859B 0004 00 00 00 00 Uncompressed Length 00000000
859F 0002 09 00 Filename Length 0009
85A1 0002 04 00 Extra Length 0004
85A3 0002 00 00 Comment Length 0000
85A5 0002 00 00 Disk Start 0000
85A7 0002 00 00 Int File Attributes 0000
[Bit 0] 0 'Binary Data'
85A9 0004 00 00 00 00 Ext File Attributes 00000000
85AD 0004 00 00 00 00 Local Header Offset 00000000
85B1 0009 4D 45 54 41 Filename 'META-INF/'
2D 49 4E 46
2F
85BA 0002 FE CA Extra ID #0001 CAFE 'Java Executable'
85BC 0002 00 00 Length 0000
...
{noformat}
Well, although this is DOS vendor, the dir byte is not set, but the filename contains a trailing slash to denote a directory. Now why does Java fail?
{code:java}
public boolean isDirectory() {
return name.endsWith("/");
}
{code}
Why does my FreeBSD {{unzip}} does work?
Magic from {{libarchive}}: https://github.com/libarchive/libarchive/blob/master/libarchive/archive_read_support_format_zip.c
{code:c}
} else if (zip_entry->system == 0) {
// Interpret MSDOS directory bit
if (0x10 == (external_attributes & 0x10)) {
zip_entry->mode = AE_IFDIR | 0775;
} else {
zip_entry->mode = AE_IFREG | 0664;
}
if (0x01 == (external_attributes & 0x01)) {
// Read-only bit; strip write permissions
zip_entry->mode &= 0555;
}
{code}
and
{code:c}
/* Make sure that entries with a trailing '/' are marked as directories
* even if the External File Attributes contains bogus values. If this
* is not a directory and there is no type, assume a regular file. */
if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) {
int has_slash;
wp = archive_entry_pathname_w(entry);
if (wp != NULL) {
len = wcslen(wp);
has_slash = len > 0 && wp[len - 1] == L'/';
} else {
cp = archive_entry_pathname(entry);
len = (cp != NULL)?strlen(cp):0;
has_slash = len > 0 && cp[len - 1] == '/';
}
/* Correct file type as needed. */
if (has_slash) {
zip_entry->mode &= ~AE_IFMT;
zip_entry->mode |= AE_IFDIR;
zip_entry->mode |= 0111;
} else if ((zip_entry->mode & AE_IFMT) == 0) {
zip_entry->mode |= AE_IFREG;
}
}
/* Make sure directories end in '/' */
if ((zip_entry->mode & AE_IFMT) == AE_IFDIR) {
wp = archive_entry_pathname_w(entry);
if (wp != NULL) {
len = wcslen(wp);
if (len > 0 && wp[len - 1] != L'/') {
struct archive_wstring s;
archive_string_init(&s);
archive_wstrcat(&s, wp);
archive_wstrappend_wchar(&s, L'/');
archive_entry_copy_pathname_w(entry, s.s);
archive_wstring_free(&s);
}
} else {
cp = archive_entry_pathname(entry);
len = (cp != NULL)?strlen(cp):0;
if (len > 0 && cp[len - 1] != '/') {
struct archive_string s;
archive_string_init(&s);
archive_strcat(&s, cp);
archive_strappend_char(&s, '/');
archive_entry_set_pathname(entry, s.s);
archive_string_free(&s);
}
}
}
{code}
Although the payload is not empty (0x03, 0x00), it is decompressed, although it does not make sense for dirs, zlib inflates this and since there is no data extracted nothing is writtten. Subsequent files in that dir likely notice that parent does not exist and create it.
So, actually both files are crap, but 1.0 just stinks more. Lets have a look at a more recent file:
{noformat}
osipovmi@deblndw011x:~/apache-maven-4.0.0-alpha-1-SNAPSHOT/lib
$ zipdetails maven-core-4.0.0-alpha-1-SNAPSHOT.jar | less
...
000E3 LOCAL HEADER #2 04034B50
000E7 Extract Zip Spec 0A '1.0'
000E8 Extract OS 00 'MS-DOS'
000E9 General Purpose Flag 0800
[Bit 11] 1 'Language Encoding'
000EB Compression Method 0000 'Stored'
000ED Last Mod Time 52854189 'Mon Apr 5 08:12:18 2021'
000F1 CRC 00000000
000F5 Compressed Length 00000000
000F9 Uncompressed Length 00000000
000FD Filename Length 0009
000FF Extra Length 0000
00101 Filename 'META-INF/'
...
967E6 CENTRAL HEADER #2 02014B50
967EA Created Zip Spec 14 '2.0'
967EB Created OS 03 'Unix'
967EC Extract Zip Spec 0A '1.0'
967ED Extract OS 00 'MS-DOS'
967EE General Purpose Flag 0800
[Bit 11] 1 'Language Encoding'
967F0 Compression Method 0000 'Stored'
967F2 Last Mod Time 52854189 'Mon Apr 5 08:12:18 2021'
967F6 CRC 00000000
967FA Compressed Length 00000000
967FE Uncompressed Length 00000000
96802 Filename Length 0009
96804 Extra Length 0000
96806 Comment Length 0000
96808 Disk Start 0000
9680A Int File Attributes 0000
[Bit 0] 0 'Binary Data'
9680C Ext File Attributes 41ED0010
[Bit 4] Directory
96810 Local Header Offset 000000E3
96814 Filename 'META-INF/'
...
{noformat}
Looks just the way is should look like, stored, trailing slash and 0x10 for directory is set int he extra file attributes.
Those old files violate:
{quote}
4.3.8 File data
Immediately following the local header for a file
SHOULD be placed the compressed or stored data for the file.
If the file is encrypted, the encryption header for the file
SHOULD be placed after the local header and before the file
data. The series of [local file header][encryption header]
[file data][data descriptor] repeats for each file in the
.ZIP archive.
Zero-byte files, directories, and other file types that
contain no content MUST NOT include file data.
{quote}
Do you rely on this file?
was (Author: michael-o):
Well, I can confirm this and thanks to you I learned a bit more about ZIP today. Lets dive into the analysis:
My setup:
{noformat}
osipovmi@deblndw011x:/tmp/maven-toolchains
$ uname -a
FreeBSD deblndw011x.ad001.siemens.net 12.2-STABLE FreeBSD 12.2-STABLE #0: Thu Sep 23 18:58:50 CEST 2021
osipovmi@deblndw011x:/tmp/maven-toolchains
$ which unzip
/usr/bin/unzip
osipovmi@deblndw011x:/tmp/maven-toolchains
$ pkg which /usr/local/bin/zipdetails
/usr/local/bin/zipdetails was installed by package perl5-5.30.3_1
osipovmi@deblndw011x:/tmp/maven-toolchains
$ java -version
openjdk version "1.8.0_302"
OpenJDK Runtime Environment (build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (build 25.302-b08, mixed mode)
{noformat}
Lets unzip first:
{noformat}
$ unzip maven-toolchain-1.0.jar
Archive: maven-toolchain-1.0.jar
extracting: META-INF
extracting: META-INF/MANIFEST.MF
extracting: org
extracting: org/apache
extracting: org/apache/maven
extracting: org/apache/maven/toolchain
extracting: org/apache/maven/toolchain/java
extracting: org/apache/maven/toolchain/java/DefaultJavaToolchainFactory.class
extracting: org/apache/maven/toolchain/java/JavaToolChain.class
extracting: org/apache/maven/toolchain/java/DefaultJavaToolChain.class
extracting: org/apache/maven/toolchain/ToolchainManagerPrivate.class
extracting: org/apache/maven/toolchain/DefaultToolchain.class
extracting: org/apache/maven/toolchain/ToolchainPrivate.class
extracting: org/apache/maven/toolchain/MisconfiguredToolchainException.class
extracting: org/apache/maven/toolchain/ToolchainManager.class
extracting: org/apache/maven/toolchain/ToolchainFactory$1.class
extracting: org/apache/maven/toolchain/model
extracting: org/apache/maven/toolchain/model/ToolchainModel.class
extracting: org/apache/maven/toolchain/model/PersistedToolchains.class
extracting: org/apache/maven/toolchain/model/io
extracting: org/apache/maven/toolchain/model/io/xpp3
extracting: org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Reader.class
extracting: org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Writer.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$ExactMatcher.class
extracting: org/apache/maven/toolchain/Toolchain.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$1.class
extracting: org/apache/maven/toolchain/ToolchainManagerPrivate$1.class
extracting: org/apache/maven/toolchain/DefaultToolchainManager.class
extracting: org/apache/maven/toolchain/ToolchainFactory.class
extracting: org/apache/maven/toolchain/ToolchainManager$1.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$VersionMatcher.class
extracting: org/apache/maven/toolchain/RequirementMatcher.class
extracting: META-INF/plexus
extracting: META-INF/plexus/components.xml
extracting: META-INF/maven
extracting: META-INF/maven/org.apache.maven
extracting: META-INF/maven/org.apache.maven/maven-toolchain
extracting: META-INF/maven/org.apache.maven/maven-toolchain/pom.xml
extracting: META-INF/maven/org.apache.maven/maven-toolchain/pom.properties
osipovmi@deblndw011x:/tmp/maven-toolchains
$ unzip maven-toolchain-2.0.9.jar
Archive: maven-toolchain-2.0.9.jar
creating: META-INF/
extracting: META-INF/MANIFEST.MF
extracting: META-INF/LICENSE
extracting: META-INF/NOTICE
creating: META-INF/plexus/
extracting: META-INF/plexus/components.xml
creating: org/
creating: org/apache/
creating: org/apache/maven/
creating: org/apache/maven/toolchain/
extracting: org/apache/maven/toolchain/DefaultToolchain.class
extracting: org/apache/maven/toolchain/DefaultToolchainManager.class
creating: org/apache/maven/toolchain/java/
extracting: org/apache/maven/toolchain/java/DefaultJavaToolChain.class
extracting: org/apache/maven/toolchain/java/DefaultJavaToolchainFactory.class
extracting: org/apache/maven/toolchain/java/JavaToolChain.class
extracting: org/apache/maven/toolchain/MisconfiguredToolchainException.class
creating: org/apache/maven/toolchain/model/
creating: org/apache/maven/toolchain/model/io/
creating: org/apache/maven/toolchain/model/io/xpp3/
extracting: org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Reader.class
extracting: org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Writer.class
extracting: org/apache/maven/toolchain/model/PersistedToolchains.class
extracting: org/apache/maven/toolchain/model/ToolchainModel.class
extracting: org/apache/maven/toolchain/RequirementMatcher.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$1.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$ExactMatcher.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory$VersionMatcher.class
extracting: org/apache/maven/toolchain/RequirementMatcherFactory.class
extracting: org/apache/maven/toolchain/Toolchain.class
extracting: org/apache/maven/toolchain/ToolchainFactory$1.class
extracting: org/apache/maven/toolchain/ToolchainFactory.class
extracting: org/apache/maven/toolchain/ToolchainManager$1.class
extracting: org/apache/maven/toolchain/ToolchainManager.class
extracting: org/apache/maven/toolchain/ToolchainManagerPrivate$1.class
extracting: org/apache/maven/toolchain/ToolchainManagerPrivate.class
extracting: org/apache/maven/toolchain/ToolchainPrivate.class
creating: META-INF/maven/
creating: META-INF/maven/org.apache.maven/
creating: META-INF/maven/org.apache.maven/maven-toolchain/
extracting: META-INF/maven/org.apache.maven/maven-toolchain/pom.xml
extracting: META-INF/maven/org.apache.maven/maven-toolchain/pom.properties
{noformat}
You already see that the output is different in 1.0 it is extracting dirs and in 2.0.x is creating them. {{unzip}} handles this case for you.
Where is the difference now?
Spec says:
{quote}
4.4.15 external file attributes: (4 bytes)
The mapping of the external attributes is
host-system dependent (see 'version made by'). For
MS-DOS, the low order byte is the MS-DOS directory
attribute byte. If input came from standard input, this
field is set to zero.
{noformat}
Lets check the ZIP details on {{META-INF}} for 1.0:
{noformat}
....
0000 0004 50 4B 03 04 LOCAL HEADER #1 04034B50
0004 0001 14 Extract Zip Spec 14 '2.0'
0005 0001 00 Extract OS 00 'MS-DOS'
0006 0002 08 00 General Purpose Flag 0008
[Bits 1-2] 0 'Normal Compression'
[Bit 3] 1 'Streamed'
0008 0002 08 00 Compression Method 0008 'Deflated'
000A 0004 70 9F 5C 38 Last Mod Time 385C9F70 'Thu Feb 28 19:59:32 2008'
000E 0004 00 00 00 00 CRC 00000000
0012 0004 00 00 00 00 Compressed Length 00000000
0016 0004 00 00 00 00 Uncompressed Length 00000000
001A 0002 08 00 Filename Length 0008
001C 0002 04 00 Extra Length 0004
001E 0008 4D 45 54 41 Filename 'META-INF'
2D 49 4E 46
0026 0002 FE CA Extra ID #0001 CAFE 'Java Executable'
0028 0002 00 00 Length 0000
002A 0002 03 00 PAYLOAD ..
...
7246 0004 50 4B 01 02 CENTRAL HEADER #1 02014B50
724A 0001 14 Created Zip Spec 14 '2.0'
724B 0001 00 Created OS 00 'MS-DOS'
724C 0001 14 Extract Zip Spec 14 '2.0'
724D 0001 00 Extract OS 00 'MS-DOS'
724E 0002 08 00 General Purpose Flag 0008
[Bits 1-2] 0 'Normal Compression'
[Bit 3] 1 'Streamed'
7250 0002 08 00 Compression Method 0008 'Deflated'
7252 0004 70 9F 5C 38 Last Mod Time 385C9F70 'Thu Feb 28 19:59:32 2008'
7256 0004 00 00 00 00 CRC 00000000
725A 0004 02 00 00 00 Compressed Length 00000002
725E 0004 00 00 00 00 Uncompressed Length 00000000
7262 0002 08 00 Filename Length 0008
7264 0002 04 00 Extra Length 0004
7266 0002 00 00 Comment Length 0000
7268 0002 00 00 Disk Start 0000
726A 0002 00 00 Int File Attributes 0000
[Bit 0] 0 'Binary Data'
726C 0004 00 00 00 00 Ext File Attributes 00000000
7270 0004 00 00 00 00 Local Header Offset 00000000
7274 0008 4D 45 54 41 Filename 'META-INF'
2D 49 4E 46
727C 0002 FE CA Extra ID #0001 CAFE 'Java Executable'
727E 0002 00 00 Length 0000
...
{noformat}
Lets check the ZIP details on {{META-INF}} for 2.0.x:
{noformat}
....
0000 0004 50 4B 03 04 LOCAL HEADER #1 04034B50
0004 0001 14 Extract Zip Spec 14 '2.0'
0005 0001 00 Extract OS 00 'MS-DOS'
0006 0002 08 00 General Purpose Flag 0008
[Bits 1-2] 0 'Normal Compression'
[Bit 3] 1 'Streamed'
0008 0002 08 00 Compression Method 0008 'Deflated'
000A 0004 D4 62 87 38 Last Mod Time 388762D4 'Mon Apr 7 12:22:40 2008'
000E 0004 00 00 00 00 CRC 00000000
0012 0004 00 00 00 00 Compressed Length 00000000
0016 0004 00 00 00 00 Uncompressed Length 00000000
001A 0002 09 00 Filename Length 0009
001C 0002 04 00 Extra Length 0004
001E 0009 4D 45 54 41 Filename 'META-INF/'
2D 49 4E 46
2F
0027 0002 FE CA Extra ID #0001 CAFE 'Java Executable'
0029 0002 00 00 Length 0000
002B 0002 03 00 PAYLOAD ..
...
8583 0004 50 4B 01 02 CENTRAL HEADER #1 02014B50
8587 0001 14 Created Zip Spec 14 '2.0'
8588 0001 00 Created OS 00 'MS-DOS'
8589 0001 14 Extract Zip Spec 14 '2.0'
858A 0001 00 Extract OS 00 'MS-DOS'
858B 0002 08 00 General Purpose Flag 0008
[Bits 1-2] 0 'Normal Compression'
[Bit 3] 1 'Streamed'
858D 0002 08 00 Compression Method 0008 'Deflated'
858F 0004 D4 62 87 38 Last Mod Time 388762D4 'Mon Apr 7 12:22:40 2008'
8593 0004 00 00 00 00 CRC 00000000
8597 0004 02 00 00 00 Compressed Length 00000002
859B 0004 00 00 00 00 Uncompressed Length 00000000
859F 0002 09 00 Filename Length 0009
85A1 0002 04 00 Extra Length 0004
85A3 0002 00 00 Comment Length 0000
85A5 0002 00 00 Disk Start 0000
85A7 0002 00 00 Int File Attributes 0000
[Bit 0] 0 'Binary Data'
85A9 0004 00 00 00 00 Ext File Attributes 00000000
85AD 0004 00 00 00 00 Local Header Offset 00000000
85B1 0009 4D 45 54 41 Filename 'META-INF/'
2D 49 4E 46
2F
85BA 0002 FE CA Extra ID #0001 CAFE 'Java Executable'
85BC 0002 00 00 Length 0000
...
{noformat}
Well, although this is DOS vendor, the dir byte is not set, but the filename contains a trailing slash to denote a directory. Now why does Java fail?
{code:java}
public boolean isDirectory() {
return name.endsWith("/");
}
{code}
Why does my FreeBSD {{unzip}} does work?
Magic from {{libarchive}}: https://github.com/libarchive/libarchive/blob/master/libarchive/archive_read_support_format_zip.c
{code:c}
} else if (zip_entry->system == 0) {
// Interpret MSDOS directory bit
if (0x10 == (external_attributes & 0x10)) {
zip_entry->mode = AE_IFDIR | 0775;
} else {
zip_entry->mode = AE_IFREG | 0664;
}
if (0x01 == (external_attributes & 0x01)) {
// Read-only bit; strip write permissions
zip_entry->mode &= 0555;
}
{code}
and
{code:c}
/* Make sure that entries with a trailing '/' are marked as directories
* even if the External File Attributes contains bogus values. If this
* is not a directory and there is no type, assume a regular file. */
if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) {
int has_slash;
wp = archive_entry_pathname_w(entry);
if (wp != NULL) {
len = wcslen(wp);
has_slash = len > 0 && wp[len - 1] == L'/';
} else {
cp = archive_entry_pathname(entry);
len = (cp != NULL)?strlen(cp):0;
has_slash = len > 0 && cp[len - 1] == '/';
}
/* Correct file type as needed. */
if (has_slash) {
zip_entry->mode &= ~AE_IFMT;
zip_entry->mode |= AE_IFDIR;
zip_entry->mode |= 0111;
} else if ((zip_entry->mode & AE_IFMT) == 0) {
zip_entry->mode |= AE_IFREG;
}
}
/* Make sure directories end in '/' */
if ((zip_entry->mode & AE_IFMT) == AE_IFDIR) {
wp = archive_entry_pathname_w(entry);
if (wp != NULL) {
len = wcslen(wp);
if (len > 0 && wp[len - 1] != L'/') {
struct archive_wstring s;
archive_string_init(&s);
archive_wstrcat(&s, wp);
archive_wstrappend_wchar(&s, L'/');
archive_entry_copy_pathname_w(entry, s.s);
archive_wstring_free(&s);
}
} else {
cp = archive_entry_pathname(entry);
len = (cp != NULL)?strlen(cp):0;
if (len > 0 && cp[len - 1] != '/') {
struct archive_string s;
archive_string_init(&s);
archive_strcat(&s, cp);
archive_strappend_char(&s, '/');
archive_entry_set_pathname(entry, s.s);
archive_string_free(&s);
}
}
}
{code}
Although the payload is not empty (0x03, 0x00), it is decompressed, although it does not make sense for dirs, zlib inflates this and since no data is there is is extracted with nothing writtten. Subsequent files in that dir likely notice that parent does not exist and create it.
So, actually both files are crap, but 1.0 jus stinks more. Lets have a look at a more recent file:
{noformat}
osipovmi@deblndw011x:~/apache-maven-4.0.0-alpha-1-SNAPSHOT/lib
$ zipdetails maven-core-4.0.0-alpha-1-SNAPSHOT.jar | less
...
000E3 LOCAL HEADER #2 04034B50
000E7 Extract Zip Spec 0A '1.0'
000E8 Extract OS 00 'MS-DOS'
000E9 General Purpose Flag 0800
[Bit 11] 1 'Language Encoding'
000EB Compression Method 0000 'Stored'
000ED Last Mod Time 52854189 'Mon Apr 5 08:12:18 2021'
000F1 CRC 00000000
000F5 Compressed Length 00000000
000F9 Uncompressed Length 00000000
000FD Filename Length 0009
000FF Extra Length 0000
00101 Filename 'META-INF/'
...
967E6 CENTRAL HEADER #2 02014B50
967EA Created Zip Spec 14 '2.0'
967EB Created OS 03 'Unix'
967EC Extract Zip Spec 0A '1.0'
967ED Extract OS 00 'MS-DOS'
967EE General Purpose Flag 0800
[Bit 11] 1 'Language Encoding'
967F0 Compression Method 0000 'Stored'
967F2 Last Mod Time 52854189 'Mon Apr 5 08:12:18 2021'
967F6 CRC 00000000
967FA Compressed Length 00000000
967FE Uncompressed Length 00000000
96802 Filename Length 0009
96804 Extra Length 0000
96806 Comment Length 0000
96808 Disk Start 0000
9680A Int File Attributes 0000
[Bit 0] 0 'Binary Data'
9680C Ext File Attributes 41ED0010
[Bit 4] Directory
96810 Local Header Offset 000000E3
96814 Filename 'META-INF/'
...
{noformat}
Looks just the way is should look like, stored, trailing slash and 0x10 for directory is set int he extra file attributes.
Do you rely on this file?
> Can't unzip/unjar maven-toolchain-1.0.jar that is available at Maven Central
> ----------------------------------------------------------------------------
>
> Key: MTOOLCHAINS-39
> URL: https://issues.apache.org/jira/browse/MTOOLCHAINS-39
> Project: Maven Toolchains Plugin
> Issue Type: Bug
> Affects Versions: 1.0
> Reporter: Thomas Cunningham
> Priority: Major
>
> jar tvf maven-toolchain-1.0.jar that is available from maven central reports reasonable results
> However....
> jar xvf doesn't work
> ❯ jar xvf maven-toolchain-1.0.jar
> inflated: META-INF
> java.io.IOException: META-INF : could not create directory
> at jdk.jartool/sun.tools.jar.Main.extractFile(Main.java:1449)
> at jdk.jartool/sun.tools.jar.Main.extract(Main.java:1364)
> at jdk.jartool/sun.tools.jar.Main.run(Main.java:409)
> at jdk.jartool/sun.tools.jar.Main.main(Main.java:1681)
> unzip doesn't work
> ❯ unzip maven-toolchain-1.0.jar
> Archive: maven-toolchain-1.0.jar
> replace META-INF? [y]es, [n]o, [A]ll, [N]one, [r]ename: A
> inflating: META-INF
> checkdir error: META-INF exists but is not directory
> unable to process META-INF/MANIFEST.MF.
> inflating: org
> checkdir error: org exists but is not directory
> unable to process org/apache.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/java.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/java/DefaultJavaToolchainFactory.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/java/JavaToolChain.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/java/DefaultJavaToolChain.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/ToolchainManagerPrivate.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/DefaultToolchain.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/ToolchainPrivate.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/MisconfiguredToolchainException.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/ToolchainManager.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/ToolchainFactory$1.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/model.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/model/ToolchainModel.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/model/PersistedToolchains.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/model/io.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/model/io/xpp3.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Reader.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/model/io/xpp3/MavenToolchainsXpp3Writer.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/RequirementMatcherFactory$ExactMatcher.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/Toolchain.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/RequirementMatcherFactory.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/RequirementMatcherFactory$1.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/ToolchainManagerPrivate$1.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/DefaultToolchainManager.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/ToolchainFactory.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/ToolchainManager$1.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/RequirementMatcherFactory$VersionMatcher.class.
> checkdir error: org exists but is not directory
> unable to process org/apache/maven/toolchain/RequirementMatcher.class.
> checkdir error: META-INF exists but is not directory
> unable to process META-INF/plexus.
> checkdir error: META-INF exists but is not directory
> unable to process META-INF/plexus/components.xml.
> checkdir error: META-INF exists but is not directory
> unable to process META-INF/maven.
> checkdir error: META-INF exists but is not directory
> unable to process META-INF/maven/org.apache.maven.
> checkdir error: META-INF exists but is not directory
> unable to process META-INF/maven/org.apache.maven/maven-toolchain.
> checkdir error: META-INF exists but is not directory
> unable to process META-INF/maven/org.apache.maven/maven-toolchain/pom.xml.
> checkdir error: META-INF exists but is not directory
> unable to process META-INF/maven/org.apache.maven/maven-toolchain/pom.properties.
>
--
This message was sent by Atlassian Jira
(v8.20.1#820001)