--- 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 {