author | sherman |
Fri, 22 Jul 2016 16:32:48 -0700 | |
changeset 39772 | c2a5d2de5253 |
parent 39771 | ab558f578f30 |
child 39773 | 0392b8791906 |
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java Fri Jul 22 16:05:23 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipEntry.java Fri Jul 22 16:32:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -568,9 +568,18 @@ int pos = off + 4; // reserved 4 bytes if (get16(extra, pos) != 0x0001 || get16(extra, pos + 2) != 24) break; - mtime = winTimeToFileTime(get64(extra, pos + 4)); - atime = winTimeToFileTime(get64(extra, pos + 12)); - ctime = winTimeToFileTime(get64(extra, pos + 20)); + long wtime = get64(extra, pos + 4); + if (wtime != WINDOWS_TIME_NOT_AVAILABLE) { + mtime = winTimeToFileTime(wtime); + } + wtime = get64(extra, pos + 12); + if (wtime != WINDOWS_TIME_NOT_AVAILABLE) { + atime = winTimeToFileTime(wtime); + } + wtime = get64(extra, pos + 20); + if (wtime != WINDOWS_TIME_NOT_AVAILABLE) { + ctime = winTimeToFileTime(wtime); + } break; case EXTID_EXTT: int flag = Byte.toUnsignedInt(extra[off]);
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java Fri Jul 22 16:05:23 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java Fri Jul 22 16:32:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -421,22 +421,36 @@ byte[] nameBytes = zc.getBytes(e.name); writeShort(nameBytes.length); - int elenEXTT = 0; // info-zip extended timestamp + int elenEXTT = 0; // info-zip extended timestamp int flagEXTT = 0; + long umtime = -1; + long uatime = -1; + long uctime = -1; if (e.mtime != null) { elenEXTT += 4; flagEXTT |= EXTT_FLAG_LMT; + umtime = fileTimeToUnixTime(e.mtime); } if (e.atime != null) { elenEXTT += 4; flagEXTT |= EXTT_FLAG_LAT; + uatime = fileTimeToUnixTime(e.atime); } if (e.ctime != null) { elenEXTT += 4; flagEXTT |= EXTT_FLAT_CT; + uctime = fileTimeToUnixTime(e.ctime); } - if (flagEXTT != 0) - elen += (elenEXTT + 5); // headid(2) + size(2) + flag(1) + data + if (flagEXTT != 0) { + // to use ntfs time if any m/a/ctime is beyond unixtime upper bound + if (umtime > UPPER_UNIXTIME_BOUND || + uatime > UPPER_UNIXTIME_BOUND || + uctime > UPPER_UNIXTIME_BOUND) { + elen += 36; // NTFS time, total 36 bytes + } else { + elen += (elenEXTT + 5); // headid(2) + size(2) + flag(1) + data + } + } writeShort(elen); writeBytes(nameBytes, 0, nameBytes.length); if (hasZip64) { @@ -446,15 +460,31 @@ writeLong(e.csize); } if (flagEXTT != 0) { - writeShort(EXTID_EXTT); - writeShort(elenEXTT + 1); // flag + data - writeByte(flagEXTT); - if (e.mtime != null) - writeInt(fileTimeToUnixTime(e.mtime)); - if (e.atime != null) - writeInt(fileTimeToUnixTime(e.atime)); - if (e.ctime != null) - writeInt(fileTimeToUnixTime(e.ctime)); + if (umtime > UPPER_UNIXTIME_BOUND || + uatime > UPPER_UNIXTIME_BOUND || + uctime > UPPER_UNIXTIME_BOUND) { + writeShort(EXTID_NTFS); // id + writeShort(32); // data size + writeInt(0); // reserved + writeShort(0x0001); // NTFS attr tag + writeShort(24); + writeLong(e.mtime == null ? WINDOWS_TIME_NOT_AVAILABLE + : fileTimeToWinTime(e.mtime)); + writeLong(e.atime == null ? WINDOWS_TIME_NOT_AVAILABLE + : fileTimeToWinTime(e.atime)); + writeLong(e.ctime == null ? WINDOWS_TIME_NOT_AVAILABLE + : fileTimeToWinTime(e.ctime)); + } else { + writeShort(EXTID_EXTT); + writeShort(elenEXTT + 1); // flag + data + writeByte(flagEXTT); + if (e.mtime != null) + writeInt(umtime); + if (e.atime != null) + writeInt(uatime); + if (e.ctime != null) + writeInt(uctime); + } } writeExtra(e.extra); locoff = written; @@ -528,18 +558,30 @@ // cen info-zip extended timestamp only outputs mtime // but set the flag for a/ctime, if present in loc int flagEXTT = 0; + long umtime = -1; + long uatime = -1; + long uctime = -1; if (e.mtime != null) { - elen += 4; // + mtime(4) flagEXTT |= EXTT_FLAG_LMT; + umtime = fileTimeToUnixTime(e.mtime); } if (e.atime != null) { flagEXTT |= EXTT_FLAG_LAT; + uatime = fileTimeToUnixTime(e.atime); } if (e.ctime != null) { flagEXTT |= EXTT_FLAT_CT; + uctime = fileTimeToUnixTime(e.ctime); } if (flagEXTT != 0) { - elen += 5; // headid + sz + flag + // to use ntfs time if any m/a/ctime is beyond unixtime upper bound + if (umtime > UPPER_UNIXTIME_BOUND || + uatime > UPPER_UNIXTIME_BOUND || + uctime > UPPER_UNIXTIME_BOUND) { + elen += 36; // NTFS time total 36 bytes + } else { + elen += 9; // headid(2) + sz(2) + flag(1) + mtime (4) + } } writeShort(elen); byte[] commentBytes; @@ -568,14 +610,30 @@ writeLong(xentry.offset); } if (flagEXTT != 0) { - writeShort(EXTID_EXTT); - if (e.mtime != null) { - writeShort(5); // flag + mtime - writeByte(flagEXTT); - writeInt(fileTimeToUnixTime(e.mtime)); + if (umtime > UPPER_UNIXTIME_BOUND || + uatime > UPPER_UNIXTIME_BOUND || + uctime > UPPER_UNIXTIME_BOUND) { + writeShort(EXTID_NTFS); // id + writeShort(32); // data size + writeInt(0); // reserved + writeShort(0x0001); // NTFS attr tag + writeShort(24); + writeLong(e.mtime == null ? WINDOWS_TIME_NOT_AVAILABLE + : fileTimeToWinTime(e.mtime)); + writeLong(e.atime == null ? WINDOWS_TIME_NOT_AVAILABLE + : fileTimeToWinTime(e.atime)); + writeLong(e.ctime == null ? WINDOWS_TIME_NOT_AVAILABLE + : fileTimeToWinTime(e.ctime)); } else { - writeShort(1); // flag only - writeByte(flagEXTT); + writeShort(EXTID_EXTT); + if (e.mtime != null) { + writeShort(5); // flag + mtime + writeByte(flagEXTT); + writeInt(umtime); + } else { + writeShort(1); // flag only + writeByte(flagEXTT); + } } } writeExtra(e.extra);
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java Fri Jul 22 16:05:23 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java Fri Jul 22 16:32:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,9 @@ // used to adjust values between Windows and java epoch private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L; + // used to indicate the corresponding windows time is not available + public static final long WINDOWS_TIME_NOT_AVAILABLE = Long.MIN_VALUE; + /** * Converts Windows time (in microseconds, UTC/GMT) time to FileTime. */ @@ -54,6 +57,11 @@ } /** + * The upper bound of the 32-bit unix time, the "year 2038 problem". + */ + public static final long UPPER_UNIXTIME_BOUND = 0x7fffffff; + + /** * Converts "standard Unix time"(in seconds, UTC/GMT) to FileTime */ public static final FileTime unixTimeToFileTime(long utime) {
--- a/jdk/test/java/util/zip/TestExtraTime.java Fri Jul 22 16:05:23 2016 +0100 +++ b/jdk/test/java/util/zip/TestExtraTime.java Fri Jul 22 16:32:48 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @bug 4759491 6303183 7012868 8015666 8023713 8068790 8076641 8075526 8130914 + * @bug 4759491 6303183 7012868 8015666 8023713 8068790 8076641 8075526 8130914 8161942 * @summary Test ZOS and ZIS timestamp in extra field correctly */ @@ -32,6 +32,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.FileTime; +import java.time.Instant; import java.util.Arrays; import java.util.TimeZone; import java.util.concurrent.TimeUnit; @@ -40,37 +41,52 @@ import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; + + public class TestExtraTime { public static void main(String[] args) throws Throwable{ File src = new File(System.getProperty("test.src", "."), "TestExtraTime.java"); - if (src.exists()) { + if (!src.exists()) { + return; + } + + TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai"); + + for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) { + + // ms-dos 1980 epoch problem + test0(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra); + // negative epoch time + test0(FileTime.from(-100, TimeUnit.DAYS), null, null, null, extra); + long time = src.lastModified(); - FileTime mtime = FileTime.from(time, TimeUnit.MILLISECONDS); - FileTime atime = FileTime.from(time + 300000, TimeUnit.MILLISECONDS); - FileTime ctime = FileTime.from(time - 300000, TimeUnit.MILLISECONDS); - TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai"); - - for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) { - test(mtime, null, null, null, extra); + test(FileTime.from(time, TimeUnit.MILLISECONDS), + FileTime.from(time + 300000, TimeUnit.MILLISECONDS), + FileTime.from(time - 300000, TimeUnit.MILLISECONDS), + tz, extra); - // ms-dos 1980 epoch problem - test(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra); - // negative epoch time - test(FileTime.from(-100, TimeUnit.DAYS), null, null, null, extra); - - // non-default tz - test(mtime, null, null, tz, extra); + // now + time = Instant.now().toEpochMilli(); + test(FileTime.from(time, TimeUnit.MILLISECONDS), + FileTime.from(time + 300000, TimeUnit.MILLISECONDS), + FileTime.from(time - 300000, TimeUnit.MILLISECONDS), + tz, extra); - test(mtime, atime, null, null, extra); - test(mtime, null, ctime, null, extra); - test(mtime, atime, ctime, null, extra); + // unix 2038 + time = 0x80000000L; + test(FileTime.from(time, TimeUnit.SECONDS), + FileTime.from(time, TimeUnit.SECONDS), + FileTime.from(time, TimeUnit.SECONDS), + tz, extra); - test(mtime, atime, null, tz, extra); - test(mtime, null, ctime, tz, extra); - test(mtime, atime, ctime, tz, extra); - } + // mtime < unix 2038 + time = 0x7fffffffL; + test(FileTime.from(time, TimeUnit.SECONDS), + FileTime.from(time + 30000, TimeUnit.SECONDS), + FileTime.from(time + 30000, TimeUnit.SECONDS), + tz, extra); } testNullHandling(); @@ -80,6 +96,18 @@ static void test(FileTime mtime, FileTime atime, FileTime ctime, TimeZone tz, byte[] extra) throws Throwable { + test0(mtime, null, null, null, extra); + test0(mtime, null, null, tz, extra); // non-default tz + test0(mtime, atime, null, null, extra); + test0(mtime, null, ctime, null, extra); + test0(mtime, atime, ctime, null, extra); + test0(mtime, atime, null, tz, extra); + test0(mtime, null, ctime, tz, extra); + test0(mtime, atime, ctime, tz, extra); + } + + static void test0(FileTime mtime, FileTime atime, FileTime ctime, + TimeZone tz, byte[] extra) throws Throwable { System.out.printf("--------------------%nTesting: [%s]/[%s]/[%s]%n", mtime, atime, ctime); TimeZone tz0 = TimeZone.getDefault(); @@ -120,13 +148,14 @@ Path zpath = Paths.get(System.getProperty("test.dir", "."), "TestExtraTime.zip"); Files.copy(new ByteArrayInputStream(baos.toByteArray()), zpath); - ZipFile zf = new ZipFile(zpath.toFile()); - ze = zf.getEntry("TestExtraTime.java"); - // ZipFile read entry from cen, which does not have a/ctime, - // for now. - check(mtime, null, null, ze, extra); - zf.close(); - Files.delete(zpath); + try (ZipFile zf = new ZipFile(zpath.toFile())) { + ze = zf.getEntry("TestExtraTime.java"); + // ZipFile read entry from cen, which does not have a/ctime, + // for now. + check(mtime, null, null, ze, extra); + } finally { + Files.delete(zpath); + } } static void check(FileTime mtime, FileTime atime, FileTime ctime,
--- a/jdk/test/java/util/zip/TestLocalTime.java Fri Jul 22 16:05:23 2016 +0100 +++ b/jdk/test/java/util/zip/TestLocalTime.java Fri Jul 22 16:32:48 2016 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 8075526 8135108 8155616 + * @bug 8075526 8135108 8155616 8161942 * @summary Test timestamp via ZipEntry.get/setTimeLocal() */ @@ -65,6 +65,9 @@ test(LocalDateTime.of(1968, 04, 28, 2, 51, 25)); test(LocalDateTime.of(1970, 04, 26, 2, 31, 52)); + // for #8161942 + test(LocalDateTime.of(2200, 04, 26, 2, 31, 52)); // unix 2038 + } finally { TimeZone.setDefault(tz0); }