diff -r 90a2bf654c4f -r 82d10099a8a6 jdk/src/share/classes/java/util/zip/ZipOutputStream.java --- a/jdk/src/share/classes/java/util/zip/ZipOutputStream.java Wed May 29 14:57:51 2013 +0100 +++ b/jdk/src/share/classes/java/util/zip/ZipOutputStream.java Wed May 29 19:50:47 2013 -0700 @@ -32,6 +32,7 @@ import java.util.Vector; import java.util.HashSet; import static java.util.zip.ZipConstants64.*; +import static java.util.zip.ZipUtils.*; /** * This class implements an output stream filter for writing files in the @@ -190,7 +191,7 @@ if (current != null) { closeEntry(); // close previous entry } - if (e.time == -1) { + if (e.mtime == -1) { e.setTime(System.currentTimeMillis()); } if (e.method == -1) { @@ -382,16 +383,25 @@ private void writeLOC(XEntry xentry) throws IOException { ZipEntry e = xentry.entry; int flag = e.flag; + boolean hasZip64 = false; int elen = (e.extra != null) ? e.extra.length : 0; - boolean hasZip64 = false; - + int eoff = 0; + boolean foundEXTT = false; // if EXTT already present + // do nothing. + while (eoff + 4 < elen) { + int tag = get16(e.extra, eoff); + int sz = get16(e.extra, eoff + 2); + if (tag == EXTID_EXTT) { + foundEXTT = true; + } + eoff += (4 + sz); + } writeInt(LOCSIG); // LOC header signature - if ((flag & 8) == 8) { writeShort(version(e)); // version needed to extract writeShort(flag); // general purpose bit flag writeShort(e.method); // compression method - writeInt(e.time); // last modification time + writeInt(javaToDosTime(e.mtime)); // last modification time // store size, uncompressed size, and crc-32 in data descriptor // immediately following compressed entry data @@ -407,7 +417,7 @@ } writeShort(flag); // general purpose bit flag writeShort(e.method); // compression method - writeInt(e.time); // last modification time + writeInt(javaToDosTime(e.mtime)); // last modification time writeInt(e.crc); // crc-32 if (hasZip64) { writeInt(ZIP64_MAGICVAL); @@ -420,6 +430,8 @@ } byte[] nameBytes = zc.getBytes(e.name); writeShort(nameBytes.length); + if (!foundEXTT) + elen += 9; // use Info-ZIP's ext time in extra writeShort(elen); writeBytes(nameBytes, 0, nameBytes.length); if (hasZip64) { @@ -428,6 +440,12 @@ writeLong(e.size); writeLong(e.csize); } + if (!foundEXTT) { + writeShort(EXTID_EXTT); + writeShort(5); // size for the folowing data block + writeByte(0x1); // flags byte, mtime only + writeInt(javaToUnixTime(e.mtime)); + } if (e.extra != null) { writeBytes(e.extra, 0, e.extra.length); } @@ -457,25 +475,25 @@ ZipEntry e = xentry.entry; int flag = e.flag; int version = version(e); - long csize = e.csize; long size = e.size; long offset = xentry.offset; - int e64len = 0; + int elenZIP64 = 0; boolean hasZip64 = false; + if (e.csize >= ZIP64_MAGICVAL) { csize = ZIP64_MAGICVAL; - e64len += 8; // csize(8) + elenZIP64 += 8; // csize(8) hasZip64 = true; } if (e.size >= ZIP64_MAGICVAL) { size = ZIP64_MAGICVAL; // size(8) - e64len += 8; + elenZIP64 += 8; hasZip64 = true; } if (xentry.offset >= ZIP64_MAGICVAL) { offset = ZIP64_MAGICVAL; - e64len += 8; // offset(8) + elenZIP64 += 8; // offset(8) hasZip64 = true; } writeInt(CENSIG); // CEN header signature @@ -488,18 +506,32 @@ } writeShort(flag); // general purpose bit flag writeShort(e.method); // compression method - writeInt(e.time); // last modification time + writeInt(javaToDosTime(e.mtime)); // last modification time writeInt(e.crc); // crc-32 writeInt(csize); // compressed size writeInt(size); // uncompressed size byte[] nameBytes = zc.getBytes(e.name); writeShort(nameBytes.length); + + int elen = (e.extra != null) ? e.extra.length : 0; + int eoff = 0; + boolean foundEXTT = false; // if EXTT already present + // do nothing. + while (eoff + 4 < elen) { + int tag = get16(e.extra, eoff); + int sz = get16(e.extra, eoff + 2); + if (tag == EXTID_EXTT) { + foundEXTT = true; + } + eoff += (4 + sz); + } if (hasZip64) { // + headid(2) + datasize(2) - writeShort(e64len + 4 + (e.extra != null ? e.extra.length : 0)); - } else { - writeShort(e.extra != null ? e.extra.length : 0); + elen += (elenZIP64 + 4); } + if (!foundEXTT) + elen += 9; // Info-ZIP's Extended Timestamp + writeShort(elen); byte[] commentBytes; if (e.comment != null) { commentBytes = zc.getBytes(e.comment); @@ -515,7 +547,7 @@ writeBytes(nameBytes, 0, nameBytes.length); if (hasZip64) { writeShort(ZIP64_EXTID);// Zip64 extra - writeShort(e64len); + writeShort(elenZIP64); if (size == ZIP64_MAGICVAL) writeLong(e.size); if (csize == ZIP64_MAGICVAL) @@ -523,6 +555,12 @@ if (offset == ZIP64_MAGICVAL) writeLong(xentry.offset); } + if (!foundEXTT) { + writeShort(EXTID_EXTT); + writeShort(5); + writeByte(0x1); // flags byte + writeInt(javaToUnixTime(e.mtime)); + } if (e.extra != null) { writeBytes(e.extra, 0, e.extra.length); } @@ -589,6 +627,15 @@ } /* + * Writes a 8-bit byte to the output stream. + */ + private void writeByte(int v) throws IOException { + OutputStream out = this.out; + out.write(v & 0xff); + written += 1; + } + + /* * Writes a 16-bit short to the output stream in little-endian byte order. */ private void writeShort(int v) throws IOException {