8015666: test/tools/pack200/TimeStamp.java failing
To keep the default behavior of ZOS unchanged, if ze extra time not explicitly set Reviewed-by: alanb, ksrini
This commit is contained in:
parent
dc14220ea6
commit
dca36c08f3
@ -71,10 +71,17 @@ interface ZipConstants {
|
||||
/*
|
||||
* Extra field header ID
|
||||
*/
|
||||
static final int EXTID_ZIP64 = 0x0001; // Zip64
|
||||
static final int EXTID_NTFS = 0x000a; // NTFS
|
||||
static final int EXTID_UNIX = 0x000d; // UNIX
|
||||
static final int EXTID_EXTT = 0x5455; // Info-ZIP Extended Timestamp
|
||||
static final int EXTID_ZIP64 = 0x0001; // Zip64
|
||||
static final int EXTID_NTFS = 0x000a; // NTFS
|
||||
static final int EXTID_UNIX = 0x000d; // UNIX
|
||||
static final int EXTID_EXTT = 0x5455; // Info-ZIP Extended Timestamp
|
||||
|
||||
/*
|
||||
* EXTT timestamp flags
|
||||
*/
|
||||
static final int EXTT_FLAG_LMT = 0x1; // LastModifiedTime
|
||||
static final int EXTT_FLAG_LAT = 0x2; // LastAccessTime
|
||||
static final int EXTT_FLAT_CT = 0x4; // CreationTime
|
||||
|
||||
/*
|
||||
* Central directory (CEN) header field offsets
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2013, 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
|
||||
@ -25,6 +25,11 @@
|
||||
|
||||
package java.util.zip;
|
||||
|
||||
import static java.util.zip.ZipUtils.*;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* This class is used to represent a ZIP file entry.
|
||||
*
|
||||
@ -32,8 +37,12 @@ package java.util.zip;
|
||||
*/
|
||||
public
|
||||
class ZipEntry implements ZipConstants, Cloneable {
|
||||
|
||||
String name; // entry name
|
||||
long mtime = -1; // last modification time
|
||||
long time = -1; // last modification time
|
||||
FileTime mtime; // last modification time, from extra field data
|
||||
FileTime atime; // last access time, from extra field data
|
||||
FileTime ctime; // creation time, from extra field data
|
||||
long crc = -1; // crc-32 of entry data
|
||||
long size = -1; // uncompressed size of entry data
|
||||
long csize = -1; // compressed size of entry data
|
||||
@ -55,15 +64,15 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
/**
|
||||
* Creates a new zip entry with the specified name.
|
||||
*
|
||||
* @param name the entry name
|
||||
* @exception NullPointerException if the entry name is null
|
||||
* @exception IllegalArgumentException if the entry name is longer than
|
||||
* 0xFFFF bytes
|
||||
* @param name
|
||||
* The entry name
|
||||
*
|
||||
* @throws NullPointerException if the entry name is null
|
||||
* @throws IllegalArgumentException if the entry name is longer than
|
||||
* 0xFFFF bytes
|
||||
*/
|
||||
public ZipEntry(String name) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
Objects.requireNonNull(name, "name");
|
||||
if (name.length() > 0xFFFF) {
|
||||
throw new IllegalArgumentException("entry name too long");
|
||||
}
|
||||
@ -73,11 +82,19 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
/**
|
||||
* Creates a new zip entry with fields taken from the specified
|
||||
* zip entry.
|
||||
* @param e a zip Entry object
|
||||
*
|
||||
* @param e
|
||||
* A zip Entry object
|
||||
*
|
||||
* @throws NullPointerException if the entry object is null
|
||||
*/
|
||||
public ZipEntry(ZipEntry e) {
|
||||
Objects.requireNonNull(e, "entry");
|
||||
name = e.name;
|
||||
time = e.time;
|
||||
mtime = e.mtime;
|
||||
atime = e.atime;
|
||||
ctime = e.ctime;
|
||||
crc = e.crc;
|
||||
size = e.size;
|
||||
csize = e.csize;
|
||||
@ -103,33 +120,178 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
/**
|
||||
* Sets the last modification time of the entry.
|
||||
*
|
||||
* @param time the last modification time of the entry in milliseconds since the epoch
|
||||
* <p> If the entry is output to a ZIP file or ZIP file formatted
|
||||
* output stream the last modification time set by this method will
|
||||
* be stored into the {@code date and time fields} of the zip file
|
||||
* entry and encoded in standard {@code MS-DOS date and time format}.
|
||||
* The {@link java.util.TimeZone#getDefault() default TimeZone} is
|
||||
* used to convert the epoch time to the MS-DOS data and time.
|
||||
*
|
||||
* @param time
|
||||
* The last modification time of the entry in milliseconds
|
||||
* since the epoch
|
||||
*
|
||||
* @see #getTime()
|
||||
* @see #getLastModifiedTime()
|
||||
*/
|
||||
public void setTime(long time) {
|
||||
this.mtime = time;
|
||||
this.time = time;
|
||||
this.mtime = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last modification time of the entry.
|
||||
* <p> The last modificatin time may come from zip entry's extensible
|
||||
* data field {@code NTFS} or {@code Info-ZIP Extended Timestamp}, if
|
||||
* the entry is read from {@link ZipInputStream} or {@link ZipFile}.
|
||||
*
|
||||
* @return the last modification time of the entry, or -1 if not specified
|
||||
* <p> If the entry is read from a ZIP file or ZIP file formatted
|
||||
* input stream, this is the last modification time from the {@code
|
||||
* date and time fields} of the zip file entry. The
|
||||
* {@link java.util.TimeZone#getDefault() default TimeZone} is used
|
||||
* to convert the standard MS-DOS formatted date and time to the
|
||||
* epoch time.
|
||||
*
|
||||
* @return The last modification time of the entry in milliseconds
|
||||
* since the epoch, or -1 if not specified
|
||||
*
|
||||
* @see #setTime(long)
|
||||
* @see #setLastModifiedTime(FileTime)
|
||||
*/
|
||||
public long getTime() {
|
||||
return mtime;
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last modification time of the entry.
|
||||
*
|
||||
* <p> When output to a ZIP file or ZIP file formatted output stream
|
||||
* the last modification time set by this method will be stored into
|
||||
* zip file entry's {@code date and time fields} in {@code standard
|
||||
* MS-DOS date and time format}), and the extended timestamp fields
|
||||
* in {@code optional extra data} in UTC time.
|
||||
*
|
||||
* @param time
|
||||
* The last modification time of the entry
|
||||
* @return This zip entry
|
||||
*
|
||||
* @throws NullPointerException if the {@code time} is null
|
||||
*
|
||||
* @see #getLastModifiedTime()
|
||||
* @since 1.8
|
||||
*/
|
||||
public ZipEntry setLastModifiedTime(FileTime time) {
|
||||
Objects.requireNonNull(name, "time");
|
||||
this.mtime = time;
|
||||
this.time = time.to(TimeUnit.MILLISECONDS);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last modification time of the entry.
|
||||
*
|
||||
* <p> If the entry is read from a ZIP file or ZIP file formatted
|
||||
* input stream, this is the last modification time from the zip
|
||||
* file entry's {@code optional extra data} if the extended timestamp
|
||||
* fields are present. Otherwise the last modification time is read
|
||||
* from the entry's {@code date and time fields}, the {@link
|
||||
* java.util.TimeZone#getDefault() default TimeZone} is used to convert
|
||||
* the standard MS-DOS formatted date and time to the epoch time.
|
||||
*
|
||||
* @return The last modification time of the entry, null if not specified
|
||||
*
|
||||
* @see #setLastModifiedTime(FileTime)
|
||||
* @since 1.8
|
||||
*/
|
||||
public FileTime getLastModifiedTime() {
|
||||
if (mtime != null)
|
||||
return mtime;
|
||||
if (time == -1)
|
||||
return null;
|
||||
return FileTime.from(time, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last access time of the entry.
|
||||
*
|
||||
* <p> If set, the last access time will be stored into the extended
|
||||
* timestamp fields of entry's {@code optional extra data}, when output
|
||||
* to a ZIP file or ZIP file formatted stream.
|
||||
*
|
||||
* @param time
|
||||
* The last access time of the entry
|
||||
* @return This zip entry
|
||||
*
|
||||
* @throws NullPointerException if the {@code time} is null
|
||||
*
|
||||
* @see #getLastAccessTime()
|
||||
* @since 1.8
|
||||
*/
|
||||
public ZipEntry setLastAccessTime(FileTime time) {
|
||||
Objects.requireNonNull(name, "time");
|
||||
this.atime = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last access time of the entry.
|
||||
*
|
||||
* <p> The last access time is from the extended timestamp fields
|
||||
* of entry's {@code optional extra data} when read from a ZIP file
|
||||
* or ZIP file formatted stream.
|
||||
*
|
||||
* @return The last access time of the entry, null if not specified
|
||||
|
||||
* @see #setLastAccessTime(long)
|
||||
* @since 1.8
|
||||
*/
|
||||
public FileTime getLastAccessTime() {
|
||||
return atime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the creation time of the entry.
|
||||
*
|
||||
* <p> If set, the creation time will be stored into the extended
|
||||
* timestamp fields of entry's {@code optional extra data}, when
|
||||
* output to a ZIP file or ZIP file formatted stream.
|
||||
*
|
||||
* @param time
|
||||
* The creation time of the entry
|
||||
* @return This zip entry
|
||||
*
|
||||
* @throws NullPointerException if the {@code time} is null
|
||||
*
|
||||
* @see #getCreationTime()
|
||||
* @since 1.8
|
||||
*/
|
||||
public ZipEntry setCreationTime(FileTime time) {
|
||||
Objects.requireNonNull(name, "time");
|
||||
this.ctime = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the creation time of the entry.
|
||||
*
|
||||
* <p> The creation time is from the extended timestamp fields of
|
||||
* entry's {@code optional extra data} when read from a ZIP file
|
||||
* or ZIP file formatted stream.
|
||||
*
|
||||
* @return the creation time of the entry, null if not specified
|
||||
* @see #setCreationTime(FileTime)
|
||||
* @since 1.8
|
||||
*/
|
||||
public FileTime getCreationTime() {
|
||||
return ctime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the uncompressed size of the entry data.
|
||||
*
|
||||
* @param size the uncompressed size in bytes
|
||||
* @exception IllegalArgumentException if the specified size is less
|
||||
* than 0, is greater than 0xFFFFFFFF when
|
||||
* <a href="package-summary.html#zip64">ZIP64 format</a> is not supported,
|
||||
* or is less than 0 when ZIP64 is supported
|
||||
*
|
||||
* @throws IllegalArgumentException if the specified size is less
|
||||
* than 0, is greater than 0xFFFFFFFF when
|
||||
* <a href="package-summary.html#zip64">ZIP64 format</a> is not supported,
|
||||
* or is less than 0 when ZIP64 is supported
|
||||
* @see #getSize()
|
||||
*/
|
||||
public void setSize(long size) {
|
||||
@ -140,7 +302,8 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the uncompressed size of the entry data, or -1 if not known.
|
||||
* Returns the uncompressed size of the entry data.
|
||||
*
|
||||
* @return the uncompressed size of the entry data, or -1 if not known
|
||||
* @see #setSize(long)
|
||||
*/
|
||||
@ -149,9 +312,11 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the compressed entry data, or -1 if not known.
|
||||
* In the case of a stored entry, the compressed size will be the same
|
||||
* Returns the size of the compressed entry data.
|
||||
*
|
||||
* <p> In the case of a stored entry, the compressed size will be the same
|
||||
* as the uncompressed size of the entry.
|
||||
*
|
||||
* @return the size of the compressed entry data, or -1 if not known
|
||||
* @see #setCompressedSize(long)
|
||||
*/
|
||||
@ -161,7 +326,9 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
|
||||
/**
|
||||
* Sets the size of the compressed entry data.
|
||||
*
|
||||
* @param csize the compressed size to set to
|
||||
*
|
||||
* @see #getCompressedSize()
|
||||
*/
|
||||
public void setCompressedSize(long csize) {
|
||||
@ -170,9 +337,11 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
|
||||
/**
|
||||
* Sets the CRC-32 checksum of the uncompressed entry data.
|
||||
*
|
||||
* @param crc the CRC-32 value
|
||||
* @exception IllegalArgumentException if the specified CRC-32 value is
|
||||
* less than 0 or greater than 0xFFFFFFFF
|
||||
*
|
||||
* @throws IllegalArgumentException if the specified CRC-32 value is
|
||||
* less than 0 or greater than 0xFFFFFFFF
|
||||
* @see #getCrc()
|
||||
*/
|
||||
public void setCrc(long crc) {
|
||||
@ -183,10 +352,11 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
|
||||
* not known.
|
||||
* Returns the CRC-32 checksum of the uncompressed entry data.
|
||||
*
|
||||
* @return the CRC-32 checksum of the uncompressed entry data, or -1 if
|
||||
* not known
|
||||
*
|
||||
* @see #setCrc(long)
|
||||
*/
|
||||
public long getCrc() {
|
||||
@ -195,9 +365,11 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
|
||||
/**
|
||||
* Sets the compression method for the entry.
|
||||
*
|
||||
* @param method the compression method, either STORED or DEFLATED
|
||||
* @exception IllegalArgumentException if the specified compression
|
||||
* method is invalid
|
||||
*
|
||||
* @throws IllegalArgumentException if the specified compression
|
||||
* method is invalid
|
||||
* @see #getMethod()
|
||||
*/
|
||||
public void setMethod(int method) {
|
||||
@ -208,7 +380,8 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the compression method of the entry, or -1 if not specified.
|
||||
* Returns the compression method of the entry.
|
||||
*
|
||||
* @return the compression method of the entry, or -1 if not specified
|
||||
* @see #setMethod(int)
|
||||
*/
|
||||
@ -218,21 +391,104 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
|
||||
/**
|
||||
* Sets the optional extra field data for the entry.
|
||||
* @param extra the extra field data bytes
|
||||
* @exception IllegalArgumentException if the length of the specified
|
||||
* extra field data is greater than 0xFFFF bytes
|
||||
*
|
||||
* <p> Invoking this method may change this entry's last modification
|
||||
* time, last access time and creation time, if the {@code extra} field
|
||||
* data includes the extensible timestamp fields, such as {@code NTFS tag
|
||||
* 0x0001} or {@code Info-ZIP Extended Timestamp}, as specified in
|
||||
* <a href="http://www.info-zip.org/doc/appnote-19970311-iz.zip">Info-ZIP
|
||||
* Application Note 970311</a>.
|
||||
*
|
||||
* @param extra
|
||||
* The extra field data bytes
|
||||
*
|
||||
* @throws IllegalArgumentException if the length of the specified
|
||||
* extra field data is greater than 0xFFFF bytes
|
||||
*
|
||||
* @see #getExtra()
|
||||
*/
|
||||
public void setExtra(byte[] extra) {
|
||||
if (extra != null && extra.length > 0xFFFF) {
|
||||
throw new IllegalArgumentException("invalid extra field length");
|
||||
setExtra0(extra, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the optional extra field data for the entry.
|
||||
*
|
||||
* @param extra
|
||||
* the extra field data bytes
|
||||
* @param doZIP64
|
||||
* if true, set size and csize from ZIP64 fields if present
|
||||
*/
|
||||
void setExtra0(byte[] extra, boolean doZIP64) {
|
||||
if (extra != null) {
|
||||
if (extra.length > 0xFFFF) {
|
||||
throw new IllegalArgumentException("invalid extra field length");
|
||||
}
|
||||
// extra fields are in "HeaderID(2)DataSize(2)Data... format
|
||||
int off = 0;
|
||||
int len = extra.length;
|
||||
while (off + 4 < len) {
|
||||
int tag = get16(extra, off);
|
||||
int sz = get16(extra, off + 2);
|
||||
off += 4;
|
||||
if (off + sz > len) // invalid data
|
||||
break;
|
||||
switch (tag) {
|
||||
case EXTID_ZIP64:
|
||||
if (doZIP64) {
|
||||
// LOC extra zip64 entry MUST include BOTH original
|
||||
// and compressed file size fields.
|
||||
// If invalid zip64 extra fields, simply skip. Even
|
||||
// it's rare, it's possible the entry size happens to
|
||||
// be the magic value and it "accidently" has some
|
||||
// bytes in extra match the id.
|
||||
if (sz >= 16) {
|
||||
size = get64(extra, off);
|
||||
csize = get64(extra, off + 8);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EXTID_NTFS:
|
||||
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));
|
||||
break;
|
||||
case EXTID_EXTT:
|
||||
int flag = Byte.toUnsignedInt(extra[off]);
|
||||
int sz0 = 1;
|
||||
// The CEN-header extra field contains the modification
|
||||
// time only, or no timestamp at all. 'sz' is used to
|
||||
// flag its presence or absence. But if mtime is present
|
||||
// in LOC it must be present in CEN as well.
|
||||
if ((flag & 0x1) != 0 && (sz0 + 4) <= sz) {
|
||||
mtime = unixTimeToFileTime(get32(extra, off + sz0));
|
||||
sz0 += 4;
|
||||
}
|
||||
if ((flag & 0x2) != 0 && (sz0 + 4) <= sz) {
|
||||
atime = unixTimeToFileTime(get32(extra, off + sz0));
|
||||
sz0 += 4;
|
||||
}
|
||||
if ((flag & 0x4) != 0 && (sz0 + 4) <= sz) {
|
||||
ctime = unixTimeToFileTime(get32(extra, off + sz0));
|
||||
sz0 += 4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
off += sz;
|
||||
}
|
||||
}
|
||||
this.extra = extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extra field data for the entry, or null if none.
|
||||
* Returns the extra field data for the entry.
|
||||
*
|
||||
* @return the extra field data for the entry, or null if none
|
||||
*
|
||||
* @see #setExtra(byte[])
|
||||
*/
|
||||
public byte[] getExtra() {
|
||||
@ -255,8 +511,10 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the comment string for the entry, or null if none.
|
||||
* Returns the comment string for the entry.
|
||||
*
|
||||
* @return the comment string for the entry, or null if none
|
||||
*
|
||||
* @see #setComment(String)
|
||||
*/
|
||||
public String getComment() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2013, 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
|
||||
@ -567,44 +567,12 @@ class ZipFile implements ZipConstants, Closeable {
|
||||
e.name = zc.toString(bname, bname.length);
|
||||
}
|
||||
}
|
||||
e.time = dosToJavaTime(getEntryTime(jzentry));
|
||||
e.crc = getEntryCrc(jzentry);
|
||||
e.size = getEntrySize(jzentry);
|
||||
e. csize = getEntryCSize(jzentry);
|
||||
e.csize = getEntryCSize(jzentry);
|
||||
e.method = getEntryMethod(jzentry);
|
||||
e.extra = getEntryBytes(jzentry, JZENTRY_EXTRA);
|
||||
if (e.extra != null) {
|
||||
byte[] extra = e.extra;
|
||||
int len = e.extra.length;
|
||||
int off = 0;
|
||||
while (off + 4 < len) {
|
||||
int pos = off;
|
||||
int tag = get16(extra, pos);
|
||||
int sz = get16(extra, pos + 2);
|
||||
pos += 4;
|
||||
if (pos + sz > len) // invalid data
|
||||
break;
|
||||
switch (tag) {
|
||||
case EXTID_NTFS:
|
||||
pos += 4; // reserved 4 bytes
|
||||
if (get16(extra, pos) != 0x0001 || get16(extra, pos + 2) != 24)
|
||||
break;
|
||||
e.mtime = winToJavaTime(get64(extra, pos + 4));
|
||||
break;
|
||||
case EXTID_EXTT:
|
||||
int flag = Byte.toUnsignedInt(extra[pos++]);
|
||||
if ((flag & 0x1) != 0) {
|
||||
e.mtime = unixToJavaTime(get32(extra, pos));
|
||||
pos += 4;
|
||||
}
|
||||
break;
|
||||
default: // unknown tag
|
||||
}
|
||||
off += (sz + 4);
|
||||
}
|
||||
}
|
||||
if (e.mtime == -1) {
|
||||
e.mtime = dosToJavaTime(getEntryTime(jzentry));
|
||||
}
|
||||
e.setExtra0(getEntryBytes(jzentry, JZENTRY_EXTRA), false);
|
||||
byte[] bcomm = getEntryBytes(jzentry, JZENTRY_COMMENT);
|
||||
if (bcomm == null) {
|
||||
e.comment = null;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2013, 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
|
||||
@ -288,9 +288,9 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
int len = get16(tmpbuf, LOCNAM);
|
||||
int blen = b.length;
|
||||
if (len > blen) {
|
||||
do
|
||||
do {
|
||||
blen = blen * 2;
|
||||
while (len > blen);
|
||||
} while (len > blen);
|
||||
b = new byte[blen];
|
||||
}
|
||||
readFully(b, 0, len);
|
||||
@ -303,7 +303,7 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
throw new ZipException("encrypted ZIP entry not supported");
|
||||
}
|
||||
e.method = get16(tmpbuf, LOCHOW);
|
||||
e.mtime = dosToJavaTime(get32(tmpbuf, LOCTIM));
|
||||
e.time = dosToJavaTime(get32(tmpbuf, LOCTIM));
|
||||
if ((flag & 8) == 8) {
|
||||
/* "Data Descriptor" present */
|
||||
if (e.method != DEFLATED) {
|
||||
@ -319,49 +319,7 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
if (len > 0) {
|
||||
byte[] extra = new byte[len];
|
||||
readFully(extra, 0, len);
|
||||
e.setExtra(extra);
|
||||
// extra fields are in "HeaderID(2)DataSize(2)Data... format
|
||||
int off = 0;
|
||||
while (off + 4 < len) {
|
||||
int pos = off;
|
||||
int tag = get16(extra, pos);
|
||||
int sz = get16(extra, pos + 2);
|
||||
pos += 4;
|
||||
if (pos + sz > len) // invalid data
|
||||
break;
|
||||
switch (tag) {
|
||||
case EXTID_ZIP64 :
|
||||
// LOC extra zip64 entry MUST include BOTH original and
|
||||
// compressed file size fields.
|
||||
//
|
||||
// If invalid zip64 extra fields, simply skip. Even it's
|
||||
// rare, it's possible the entry size happens to be
|
||||
// the magic value and it "accidently" has some bytes
|
||||
// in extra match the id.
|
||||
if (sz >= 16 && (pos + sz) <= len ) {
|
||||
e.size = get64(extra, pos);
|
||||
e.csize = get64(extra, pos + 8);
|
||||
}
|
||||
break;
|
||||
case EXTID_NTFS:
|
||||
pos += 4; // reserved 4 bytes
|
||||
if (get16(extra, pos) != 0x0001 || get16(extra, pos + 2) != 24)
|
||||
break;
|
||||
// override the loc field, NTFS time has 'microsecond' granularity
|
||||
e.mtime = winToJavaTime(get64(extra, pos + 4));
|
||||
break;
|
||||
case EXTID_EXTT:
|
||||
int flag = Byte.toUnsignedInt(extra[pos++]);
|
||||
if ((flag & 0x1) != 0) {
|
||||
e.mtime = unixToJavaTime(get32(extra, pos));
|
||||
pos += 4;
|
||||
}
|
||||
break;
|
||||
default: // unknown tag
|
||||
}
|
||||
off += (sz + 4);
|
||||
}
|
||||
|
||||
e.setExtra0(extra, true);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
@ -59,8 +59,9 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
"jdk.util.zip.inhibitZip64", "false")));
|
||||
|
||||
private static class XEntry {
|
||||
public final ZipEntry entry;
|
||||
public final long offset;
|
||||
final ZipEntry entry;
|
||||
final long offset;
|
||||
long dostime; // last modification time in msdos format
|
||||
public XEntry(ZipEntry entry, long offset) {
|
||||
this.entry = entry;
|
||||
this.offset = offset;
|
||||
@ -191,7 +192,9 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
if (current != null) {
|
||||
closeEntry(); // close previous entry
|
||||
}
|
||||
if (e.mtime == -1) {
|
||||
if (e.time == -1) {
|
||||
// by default, do NOT use extended timestamps in extra
|
||||
// data, for now.
|
||||
e.setTime(System.currentTimeMillis());
|
||||
}
|
||||
if (e.method == -1) {
|
||||
@ -384,25 +387,20 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
ZipEntry e = xentry.entry;
|
||||
int flag = e.flag;
|
||||
boolean hasZip64 = false;
|
||||
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);
|
||||
}
|
||||
int elen = getExtraLen(e.extra);
|
||||
|
||||
// keep a copy of dostime for writeCEN(), otherwise the tz
|
||||
// sensitive local time entries in loc and cen might be
|
||||
// different if the default tz get changed during writeLOC()
|
||||
// and writeCEN()
|
||||
xentry.dostime = javaToDosTime(e.time);
|
||||
|
||||
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(javaToDosTime(e.mtime)); // last modification time
|
||||
|
||||
writeInt(xentry.dostime); // last modification time
|
||||
// store size, uncompressed size, and crc-32 in data descriptor
|
||||
// immediately following compressed entry data
|
||||
writeInt(0);
|
||||
@ -417,7 +415,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
}
|
||||
writeShort(flag); // general purpose bit flag
|
||||
writeShort(e.method); // compression method
|
||||
writeInt(javaToDosTime(e.mtime)); // last modification time
|
||||
writeInt(xentry.dostime); // last modification time
|
||||
writeInt(e.crc); // crc-32
|
||||
if (hasZip64) {
|
||||
writeInt(ZIP64_MAGICVAL);
|
||||
@ -430,8 +428,23 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
}
|
||||
byte[] nameBytes = zc.getBytes(e.name);
|
||||
writeShort(nameBytes.length);
|
||||
if (!foundEXTT)
|
||||
elen += 9; // use Info-ZIP's ext time in extra
|
||||
|
||||
int elenEXTT = 0; // info-zip extended timestamp
|
||||
int flagEXTT = 0;
|
||||
if (e.mtime != null) {
|
||||
elenEXTT += 4;
|
||||
flagEXTT |= EXTT_FLAG_LMT;
|
||||
}
|
||||
if (e.atime != null) {
|
||||
elenEXTT += 4;
|
||||
flagEXTT |= EXTT_FLAG_LAT;
|
||||
}
|
||||
if (e.ctime != null) {
|
||||
elenEXTT += 4;
|
||||
flagEXTT |= EXTT_FLAT_CT;
|
||||
}
|
||||
if (flagEXTT != 0)
|
||||
elen += (elenEXTT + 5); // headid(2) + size(2) + flag(1) + data
|
||||
writeShort(elen);
|
||||
writeBytes(nameBytes, 0, nameBytes.length);
|
||||
if (hasZip64) {
|
||||
@ -440,15 +453,18 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeLong(e.size);
|
||||
writeLong(e.csize);
|
||||
}
|
||||
if (!foundEXTT) {
|
||||
if (flagEXTT != 0) {
|
||||
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);
|
||||
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));
|
||||
}
|
||||
writeExtra(e.extra);
|
||||
locoff = written;
|
||||
}
|
||||
|
||||
@ -506,31 +522,35 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
}
|
||||
writeShort(flag); // general purpose bit flag
|
||||
writeShort(e.method); // compression method
|
||||
writeInt(javaToDosTime(e.mtime)); // last modification time
|
||||
// use the copy in xentry, which has been converted
|
||||
// from e.time in writeLOC()
|
||||
writeInt(xentry.dostime); // 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);
|
||||
}
|
||||
int elen = getExtraLen(e.extra);
|
||||
if (hasZip64) {
|
||||
// + headid(2) + datasize(2)
|
||||
elen += (elenZIP64 + 4);
|
||||
elen += (elenZIP64 + 4);// + headid(2) + datasize(2)
|
||||
}
|
||||
// cen info-zip extended timestamp only outputs mtime
|
||||
// but set the flag for a/ctime, if present in loc
|
||||
int flagEXTT = 0;
|
||||
if (e.mtime != null) {
|
||||
elen += 4; // + mtime(4)
|
||||
flagEXTT |= EXTT_FLAG_LMT;
|
||||
}
|
||||
if (e.atime != null) {
|
||||
flagEXTT |= EXTT_FLAG_LAT;
|
||||
}
|
||||
if (e.ctime != null) {
|
||||
flagEXTT |= EXTT_FLAT_CT;
|
||||
}
|
||||
if (flagEXTT != 0) {
|
||||
elen += 5; // headid + sz + flag
|
||||
}
|
||||
if (!foundEXTT)
|
||||
elen += 9; // Info-ZIP's Extended Timestamp
|
||||
writeShort(elen);
|
||||
byte[] commentBytes;
|
||||
if (e.comment != null) {
|
||||
@ -545,6 +565,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeInt(0); // external file attributes (unused)
|
||||
writeInt(offset); // relative offset of local header
|
||||
writeBytes(nameBytes, 0, nameBytes.length);
|
||||
|
||||
// take care of EXTID_ZIP64 and EXTID_EXTT
|
||||
if (hasZip64) {
|
||||
writeShort(ZIP64_EXTID);// Zip64 extra
|
||||
writeShort(elenZIP64);
|
||||
@ -555,15 +577,18 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
if (offset == ZIP64_MAGICVAL)
|
||||
writeLong(xentry.offset);
|
||||
}
|
||||
if (!foundEXTT) {
|
||||
if (flagEXTT != 0) {
|
||||
writeShort(EXTID_EXTT);
|
||||
writeShort(5);
|
||||
writeByte(0x1); // flags byte
|
||||
writeInt(javaToUnixTime(e.mtime));
|
||||
}
|
||||
if (e.extra != null) {
|
||||
writeBytes(e.extra, 0, e.extra.length);
|
||||
if (e.mtime != null) {
|
||||
writeShort(5); // flag + mtime
|
||||
writeByte(flagEXTT);
|
||||
writeInt(fileTimeToUnixTime(e.mtime));
|
||||
} else {
|
||||
writeShort(1); // flag only
|
||||
writeByte(flagEXTT);
|
||||
}
|
||||
}
|
||||
writeExtra(e.extra);
|
||||
if (commentBytes != null) {
|
||||
writeBytes(commentBytes, 0, Math.min(commentBytes.length, 0xffff));
|
||||
}
|
||||
@ -626,6 +651,47 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of extra data without EXTT and ZIP64.
|
||||
*/
|
||||
private int getExtraLen(byte[] extra) {
|
||||
if (extra == null)
|
||||
return 0;
|
||||
int skipped = 0;
|
||||
int len = extra.length;
|
||||
int off = 0;
|
||||
while (off + 4 <= len) {
|
||||
int tag = get16(extra, off);
|
||||
int sz = get16(extra, off + 2);
|
||||
if (tag == EXTID_EXTT || tag == EXTID_ZIP64) {
|
||||
skipped += (sz + 4);
|
||||
}
|
||||
off += (sz + 4);
|
||||
}
|
||||
return len - skipped;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes extra data without EXTT and ZIP64.
|
||||
*
|
||||
* Extra timestamp and ZIP64 data is handled/output separately
|
||||
* in writeLOC and writeCEN.
|
||||
*/
|
||||
private void writeExtra(byte[] extra) throws IOException {
|
||||
if (extra != null) {
|
||||
int len = extra.length;
|
||||
int off = 0;
|
||||
while (off + 4 <= len) {
|
||||
int tag = get16(extra, off);
|
||||
int sz = get16(extra, off + 2);
|
||||
if (tag != EXTID_EXTT && tag != EXTID_ZIP64) {
|
||||
writeBytes(extra, off, sz + 4);
|
||||
}
|
||||
off += (sz + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a 8-bit byte to the output stream.
|
||||
*/
|
||||
|
@ -25,42 +25,45 @@
|
||||
|
||||
package java.util.zip;
|
||||
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static java.util.zip.ZipConstants.*;
|
||||
import static java.util.zip.ZipConstants64.*;
|
||||
|
||||
class ZipUtils {
|
||||
|
||||
// used to adjust values between Windows and java epoch
|
||||
private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
|
||||
|
||||
/**
|
||||
* Converts Windows time (in microseconds, UTC/GMT) time to Java time.
|
||||
* Converts Windows time (in microseconds, UTC/GMT) time to FileTime.
|
||||
*/
|
||||
public static final long winToJavaTime(long wtime) {
|
||||
return TimeUnit.MILLISECONDS.convert(
|
||||
wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS, TimeUnit.MICROSECONDS);
|
||||
public static final FileTime winTimeToFileTime(long wtime) {
|
||||
return FileTime.from(wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS,
|
||||
TimeUnit.MICROSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Java time to Windows time.
|
||||
* Converts FileTime to Windows time.
|
||||
*/
|
||||
public static final long javaToWinTime(long time) {
|
||||
return (TimeUnit.MICROSECONDS.convert(time, TimeUnit.MILLISECONDS)
|
||||
- WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
|
||||
public static final long fileTimeToWinTime(FileTime ftime) {
|
||||
return (ftime.to(TimeUnit.MICROSECONDS) - WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts "standard Unix time"(in seconds, UTC/GMT) to Java time
|
||||
* Converts "standard Unix time"(in seconds, UTC/GMT) to FileTime
|
||||
*/
|
||||
public static final long unixToJavaTime(long utime) {
|
||||
return TimeUnit.MILLISECONDS.convert(utime, TimeUnit.SECONDS);
|
||||
public static final FileTime unixTimeToFileTime(long utime) {
|
||||
return FileTime.from(utime, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Java time to "standard Unix time".
|
||||
* Converts FileTime to "standard Unix time".
|
||||
*/
|
||||
public static final long javaToUnixTime(long time) {
|
||||
return TimeUnit.SECONDS.convert(time, TimeUnit.MILLISECONDS);
|
||||
public static final long fileTimeToUnixTime(FileTime ftime) {
|
||||
return ftime.to(TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,7 +95,6 @@ class ZipUtils {
|
||||
d.getSeconds() >> 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches unsigned 16-bit value from byte array at specified offset.
|
||||
* The bytes are assumed to be in Intel (little-endian) byte order.
|
||||
@ -116,5 +118,4 @@ class ZipUtils {
|
||||
public static final long get64(byte b[], int off) {
|
||||
return get32(b, off) | (get32(b, off+4) << 32);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -335,8 +335,6 @@ sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
|
||||
# Tests take too long, on sparcs see 7143279
|
||||
tools/pack200/CommandLineTests.java solaris-all, macosx-all
|
||||
tools/pack200/Pack200Test.java solaris-all, macosx-all
|
||||
# 8015666
|
||||
tools/pack200/TimeStamp.java generic-all
|
||||
|
||||
# 8007410
|
||||
tools/launcher/FXLauncherTest.java linux-all
|
||||
|
@ -23,14 +23,19 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4759491 6303183 7012868
|
||||
* @bug 4759491 6303183 7012868 8015666
|
||||
* @summary Test ZOS and ZIS timestamp in extra field correctly
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@ -41,14 +46,32 @@ public class TestExtraTime {
|
||||
|
||||
File src = new File(System.getProperty("test.src", "."), "TestExtraTime.java");
|
||||
if (src.exists()) {
|
||||
long mtime = src.lastModified();
|
||||
test(mtime, null);
|
||||
test(10, null); // ms-dos 1980 epoch problem
|
||||
test(mtime, TimeZone.getTimeZone("Asia/Shanghai"));
|
||||
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");
|
||||
|
||||
test(mtime, null, null, null);
|
||||
// ms-dos 1980 epoch problem
|
||||
test(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null);
|
||||
// non-default tz
|
||||
test(mtime, null, null, tz);
|
||||
|
||||
test(mtime, atime, null, null);
|
||||
test(mtime, null, ctime, null);
|
||||
test(mtime, atime, ctime, null);
|
||||
|
||||
test(mtime, atime, null, tz);
|
||||
test(mtime, null, ctime, tz);
|
||||
test(mtime, atime, ctime, tz);
|
||||
}
|
||||
}
|
||||
|
||||
private static void test(long mtime, TimeZone tz) throws Throwable {
|
||||
static void test(FileTime mtime, FileTime atime, FileTime ctime,
|
||||
TimeZone tz) throws Throwable {
|
||||
System.out.printf("--------------------%nTesting: [%s]/[%s]/[%s]%n",
|
||||
mtime, atime, ctime);
|
||||
TimeZone tz0 = TimeZone.getDefault();
|
||||
if (tz != null) {
|
||||
TimeZone.setDefault(tz);
|
||||
@ -57,23 +80,55 @@ public class TestExtraTime {
|
||||
ZipOutputStream zos = new ZipOutputStream(baos);
|
||||
ZipEntry ze = new ZipEntry("TestExtreTime.java");
|
||||
|
||||
ze.setTime(mtime);
|
||||
ze.setLastModifiedTime(mtime);
|
||||
if (atime != null)
|
||||
ze.setLastAccessTime(atime);
|
||||
if (ctime != null)
|
||||
ze.setCreationTime(ctime);
|
||||
zos.putNextEntry(ze);
|
||||
zos.write(new byte[] { 1,2 ,3, 4});
|
||||
zos.close();
|
||||
if (tz != null) {
|
||||
TimeZone.setDefault(tz0);
|
||||
}
|
||||
// ZipInputStream
|
||||
ZipInputStream zis = new ZipInputStream(
|
||||
new ByteArrayInputStream(baos.toByteArray()));
|
||||
ze = zis.getNextEntry();
|
||||
zis.close();
|
||||
check(mtime, atime, ctime, ze);
|
||||
|
||||
System.out.printf("%tc => %tc%n", mtime, ze.getTime());
|
||||
|
||||
if (TimeUnit.MILLISECONDS.toSeconds(mtime) !=
|
||||
TimeUnit.MILLISECONDS.toSeconds(ze.getTime()))
|
||||
throw new RuntimeException("Timestamp storing failed!");
|
||||
// ZipFile
|
||||
Path zpath = Paths.get(System.getProperty("test.dir", "."),
|
||||
"TestExtraTimp.zip");
|
||||
Files.copy(new ByteArrayInputStream(baos.toByteArray()), zpath);
|
||||
ZipFile zf = new ZipFile(zpath.toFile());
|
||||
ze = zf.getEntry("TestExtreTime.java");
|
||||
// ZipFile read entry from cen, which does not have a/ctime,
|
||||
// for now.
|
||||
check(mtime, null, null, ze);
|
||||
zf.close();
|
||||
Files.delete(zpath);
|
||||
}
|
||||
|
||||
static void check(FileTime mtime, FileTime atime, FileTime ctime,
|
||||
ZipEntry ze) {
|
||||
/*
|
||||
System.out.printf(" mtime [%tc]: [%tc]/[%tc]%n",
|
||||
mtime.to(TimeUnit.MILLISECONDS),
|
||||
ze.getTime(),
|
||||
ze.getLastModifiedTime().to(TimeUnit.MILLISECONDS));
|
||||
*/
|
||||
if (mtime.to(TimeUnit.SECONDS) !=
|
||||
ze.getLastModifiedTime().to(TimeUnit.SECONDS))
|
||||
throw new RuntimeException("Timestamp: storing mtime failed!");
|
||||
if (atime != null &&
|
||||
atime.to(TimeUnit.SECONDS) !=
|
||||
ze.getLastAccessTime().to(TimeUnit.SECONDS))
|
||||
throw new RuntimeException("Timestamp: storing atime failed!");
|
||||
if (ctime != null &&
|
||||
ctime.to(TimeUnit.SECONDS) !=
|
||||
ze.getCreationTime().to(TimeUnit.SECONDS))
|
||||
throw new RuntimeException("Timestamp: storing ctime failed!");
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ public class TimeStamp {
|
||||
unpackNative(packFile, pstFile);
|
||||
verifyJar(goldenFile, pstFile);
|
||||
pstFile.delete();
|
||||
Utils.cleanup();
|
||||
}
|
||||
|
||||
static void unpackNative(File packFile, File outFile) {
|
||||
@ -149,7 +150,6 @@ public class TimeStamp {
|
||||
Utils.close(jf1);
|
||||
Utils.close(jf2);
|
||||
}
|
||||
Utils.cleanup();
|
||||
if (errors > 0) {
|
||||
throw new RuntimeException("FAIL:" + errors + " error(s) encounted");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user