From 8aa540d2f783474d1d2e06f16744bf67b9c1facc Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 10 Mar 2006 21:46:48 +0000 Subject: Imported GNU Classpath 0.90 Imported GNU Classpath 0.90 * scripts/makemake.tcl: Set gnu/java/awt/peer/swing to ignore. * gnu/classpath/jdwp/VMFrame.java (SIZE): New constant. * java/lang/VMCompiler.java: Use gnu.java.security.hash.MD5. * java/lang/Math.java: New override file. * java/lang/Character.java: Merged from Classpath. (start, end): Now 'int's. (canonicalName): New field. (CANONICAL_NAME, NO_SPACES_NAME, CONSTANT_NAME): New constants. (UnicodeBlock): Added argument. (of): New overload. (forName): New method. Updated unicode blocks. (sets): Updated. * sources.am: Regenerated. * Makefile.in: Likewise. From-SVN: r111942 --- libjava/classpath/java/util/zip/ZipConstants.java | 10 +- libjava/classpath/java/util/zip/ZipFile.java | 397 +++++++++++---------- .../classpath/java/util/zip/ZipOutputStream.java | 12 +- 3 files changed, 220 insertions(+), 199 deletions(-) (limited to 'libjava/classpath/java/util/zip') diff --git a/libjava/classpath/java/util/zip/ZipConstants.java b/libjava/classpath/java/util/zip/ZipConstants.java index 952a44d..6d66419 100644 --- a/libjava/classpath/java/util/zip/ZipConstants.java +++ b/libjava/classpath/java/util/zip/ZipConstants.java @@ -1,5 +1,5 @@ /* java.util.zip.ZipConstants - Copyright (C) 2001 Free Software Foundation, Inc. + Copyright (C) 2001, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,7 +41,7 @@ interface ZipConstants { /* The local file header */ int LOCHDR = 30; - int LOCSIG = 'P'|('K'<<8)|(3<<16)|(4<<24); + long LOCSIG = 'P'|('K'<<8)|(3<<16)|(4<<24); int LOCVER = 4; int LOCFLG = 6; @@ -54,7 +54,7 @@ interface ZipConstants int LOCEXT = 28; /* The Data descriptor */ - int EXTSIG = 'P'|('K'<<8)|(7<<16)|(8<<24); + long EXTSIG = 'P'|('K'<<8)|(7<<16)|(8<<24); int EXTHDR = 16; int EXTCRC = 4; @@ -62,7 +62,7 @@ interface ZipConstants int EXTLEN = 12; /* The central directory file header */ - int CENSIG = 'P'|('K'<<8)|(1<<16)|(2<<24); + long CENSIG = 'P'|('K'<<8)|(1<<16)|(2<<24); int CENHDR = 46; int CENVEM = 4; @@ -82,7 +82,7 @@ interface ZipConstants int CENOFF = 42; /* The entries in the end of central directory */ - int ENDSIG = 'P'|('K'<<8)|(5<<16)|(6<<24); + long ENDSIG = 'P'|('K'<<8)|(5<<16)|(6<<24); int ENDHDR = 22; /* The following two fields are missing in SUN JDK */ diff --git a/libjava/classpath/java/util/zip/ZipFile.java b/libjava/classpath/java/util/zip/ZipFile.java index 4be845e..7307ee9 100644 --- a/libjava/classpath/java/util/zip/ZipFile.java +++ b/libjava/classpath/java/util/zip/ZipFile.java @@ -1,5 +1,5 @@ /* ZipFile.java -- - Copyright (C) 2001, 2002, 2003, 2004, 2005 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,8 +41,6 @@ package java.util.zip; import gnu.java.util.EmptyEnumeration; -import java.io.BufferedInputStream; -import java.io.DataInput; import java.io.EOFException; import java.io.File; import java.io.IOException; @@ -141,23 +139,33 @@ public class ZipFile implements ZipConstants checkZipFile(); } - private void checkZipFile() throws IOException, ZipException + private void checkZipFile() throws ZipException { - byte[] magicBuf = new byte[4]; - boolean validRead = true; + boolean valid = false; try { - raf.readFully(magicBuf); - } - catch (EOFException eof) + byte[] buf = new byte[4]; + raf.readFully(buf); + int sig = buf[0] & 0xFF + | ((buf[1] & 0xFF) << 8) + | ((buf[2] & 0xFF) << 16) + | ((buf[3] & 0xFF) << 24); + valid = sig == LOCSIG; + } + catch (IOException _) { - validRead = false; } - if (validRead == false || readLeInt(magicBuf, 0) != LOCSIG) + if (!valid) { - raf.close(); + try + { + raf.close(); + } + catch (IOException _) + { + } throw new ZipException("Not a valid zip file"); } } @@ -172,69 +180,6 @@ public class ZipFile implements ZipConstants } /** - * Read an unsigned short in little endian byte order from the given - * DataInput stream using the given byte buffer. - * - * @param di DataInput stream to read from. - * @param b the byte buffer to read in (must be at least 2 bytes long). - * @return The value read. - * - * @exception IOException if a i/o error occured. - * @exception EOFException if the file ends prematurely - */ - private int readLeShort(DataInput di, byte[] b) throws IOException - { - di.readFully(b, 0, 2); - return (b[0] & 0xff) | (b[1] & 0xff) << 8; - } - - /** - * Read an int in little endian byte order from the given - * DataInput stream using the given byte buffer. - * - * @param di DataInput stream to read from. - * @param b the byte buffer to read in (must be at least 4 bytes long). - * @return The value read. - * - * @exception IOException if a i/o error occured. - * @exception EOFException if the file ends prematurely - */ - private int readLeInt(DataInput di, byte[] b) throws IOException - { - di.readFully(b, 0, 4); - return ((b[0] & 0xff) | (b[1] & 0xff) << 8) - | ((b[2] & 0xff) | (b[3] & 0xff) << 8) << 16; - } - - /** - * Read an unsigned short in little endian byte order from the given - * byte buffer at the given offset. - * - * @param b the byte array to read from. - * @param off the offset to read from. - * @return The value read. - */ - private int readLeShort(byte[] b, int off) - { - return (b[off] & 0xff) | (b[off+1] & 0xff) << 8; - } - - /** - * Read an int in little endian byte order from the given - * byte buffer at the given offset. - * - * @param b the byte array to read from. - * @param off the offset to read from. - * @return The value read. - */ - private int readLeInt(byte[] b, int off) - { - return ((b[off] & 0xff) | (b[off+1] & 0xff) << 8) - | ((b[off+2] & 0xff) | (b[off+3] & 0xff) << 8) << 16; - } - - - /** * Read the central directory of a zip file and fill the entries * array. This is called exactly once when first needed. It is called * while holding the lock on raf. @@ -246,63 +191,48 @@ public class ZipFile implements ZipConstants { /* Search for the End Of Central Directory. When a zip comment is * present the directory may start earlier. - * FIXME: This searches the whole file in a very slow manner if the - * file isn't a zip file. + * Note that a comment has a maximum length of 64K, so that is the + * maximum we search backwards. */ + PartialInputStream inp = new PartialInputStream(raf, 4096); long pos = raf.length() - ENDHDR; - byte[] ebs = new byte[CENHDR]; - + long top = Math.max(0, pos - 65536); do { - if (pos < 0) + if (pos < top) throw new ZipException ("central directory not found, probably not a zip file: " + name); - raf.seek(pos--); + inp.seek(pos--); } - while (readLeInt(raf, ebs) != ENDSIG); + while (inp.readLeInt() != ENDSIG); - if (raf.skipBytes(ENDTOT - ENDNRD) != ENDTOT - ENDNRD) + if (inp.skip(ENDTOT - ENDNRD) != ENDTOT - ENDNRD) throw new EOFException(name); - int count = readLeShort(raf, ebs); - if (raf.skipBytes(ENDOFF - ENDSIZ) != ENDOFF - ENDSIZ) + int count = inp.readLeShort(); + if (inp.skip(ENDOFF - ENDSIZ) != ENDOFF - ENDSIZ) throw new EOFException(name); - int centralOffset = readLeInt(raf, ebs); + int centralOffset = inp.readLeInt(); entries = new HashMap(count+count/2); - raf.seek(centralOffset); + inp.seek(centralOffset); - byte[] buffer = new byte[16]; for (int i = 0; i < count; i++) { - raf.readFully(ebs); - if (readLeInt(ebs, 0) != CENSIG) + if (inp.readLeInt() != CENSIG) throw new ZipException("Wrong Central Directory signature: " + name); - int method = readLeShort(ebs, CENHOW); - int dostime = readLeInt(ebs, CENTIM); - int crc = readLeInt(ebs, CENCRC); - int csize = readLeInt(ebs, CENSIZ); - int size = readLeInt(ebs, CENLEN); - int nameLen = readLeShort(ebs, CENNAM); - int extraLen = readLeShort(ebs, CENEXT); - int commentLen = readLeShort(ebs, CENCOM); - - int offset = readLeInt(ebs, CENOFF); - - int needBuffer = Math.max(nameLen, commentLen); - if (buffer.length < needBuffer) - buffer = new byte[needBuffer]; - - raf.readFully(buffer, 0, nameLen); - String name; - try - { - name = new String(buffer, 0, nameLen, "UTF-8"); - } - catch (UnsupportedEncodingException uee) - { - throw new AssertionError(uee); - } + inp.skip(6); + int method = inp.readLeShort(); + int dostime = inp.readLeInt(); + int crc = inp.readLeInt(); + int csize = inp.readLeInt(); + int size = inp.readLeInt(); + int nameLen = inp.readLeShort(); + int extraLen = inp.readLeShort(); + int commentLen = inp.readLeShort(); + inp.skip(8); + int offset = inp.readLeInt(); + String name = inp.readString(nameLen); ZipEntry entry = new ZipEntry(name); entry.setMethod(method); @@ -313,20 +243,12 @@ public class ZipFile implements ZipConstants if (extraLen > 0) { byte[] extra = new byte[extraLen]; - raf.readFully(extra); + inp.readFully(extra); entry.setExtra(extra); } if (commentLen > 0) { - raf.readFully(buffer, 0, commentLen); - try - { - entry.setComment(new String(buffer, 0, commentLen, "UTF-8")); - } - catch (UnsupportedEncodingException uee) - { - throw new AssertionError(uee); - } + entry.setComment(inp.readString(commentLen)); } entry.offset = offset; entries.put(name, entry); @@ -429,42 +351,6 @@ public class ZipFile implements ZipConstants } } - - //access should be protected by synchronized(raf) - private byte[] locBuf = new byte[LOCHDR]; - - /** - * Checks, if the local header of the entry at index i matches the - * central directory, and returns the offset to the data. - * - * @param entry to check. - * @return the start offset of the (compressed) data. - * - * @exception IOException if a i/o error occured. - * @exception ZipException if the local header doesn't match the - * central directory header - */ - private long checkLocalHeader(ZipEntry entry) throws IOException - { - synchronized (raf) - { - raf.seek(entry.offset); - raf.readFully(locBuf); - - if (readLeInt(locBuf, 0) != LOCSIG) - throw new ZipException("Wrong Local header signature: " + name); - - if (entry.getMethod() != readLeShort(locBuf, LOCHOW)) - throw new ZipException("Compression method mismatch: " + name); - - if (entry.getName().length() != readLeShort(locBuf, LOCNAM)) - throw new ZipException("file name length mismatch: " + name); - - int extraLen = entry.getName().length() + readLeShort(locBuf, LOCEXT); - return entry.offset + LOCHDR + extraLen; - } - } - /** * Creates an input stream reading the given zip entry as * uncompressed data. Normally zip entry should be an entry @@ -497,16 +383,32 @@ public class ZipFile implements ZipConstants if (zipEntry == null) return null; - long start = checkLocalHeader(zipEntry); + PartialInputStream inp = new PartialInputStream(raf, 1024); + inp.seek(zipEntry.offset); + + if (inp.readLeInt() != LOCSIG) + throw new ZipException("Wrong Local header signature: " + name); + + inp.skip(4); + + if (zipEntry.getMethod() != inp.readLeShort()) + throw new ZipException("Compression method mismatch: " + name); + + inp.skip(16); + + int nameLen = inp.readLeShort(); + int extraLen = inp.readLeShort(); + inp.skip(nameLen + extraLen); + + inp.setLength(zipEntry.getCompressedSize()); + int method = zipEntry.getMethod(); - InputStream is = new BufferedInputStream(new PartialInputStream - (raf, start, zipEntry.getCompressedSize())); switch (method) { case ZipOutputStream.STORED: - return is; + return inp; case ZipOutputStream.DEFLATED: - return new InflaterInputStream(is, new Inflater(true)); + return new InflaterInputStream(inp, new Inflater(true)); default: throw new ZipException("Unknown compression method " + method); } @@ -562,21 +464,41 @@ public class ZipFile implements ZipConstants } } - private static class PartialInputStream extends InputStream + private static final class PartialInputStream extends InputStream { private final RandomAccessFile raf; - long filepos, end; + private final byte[] buffer; + private long bufferOffset; + private int pos; + private long end; - public PartialInputStream(RandomAccessFile raf, long start, long len) + public PartialInputStream(RandomAccessFile raf, int bufferSize) + throws IOException { this.raf = raf; - filepos = start; - end = start + len; + buffer = new byte[bufferSize]; + bufferOffset = -buffer.length; + pos = buffer.length; + end = raf.length(); + } + + void setLength(long length) + { + end = bufferOffset + pos + length; + } + + private void fillBuffer() throws IOException + { + synchronized (raf) + { + raf.seek(bufferOffset); + raf.readFully(buffer, 0, (int) Math.min(buffer.length, end - bufferOffset)); + } } public int available() { - long amount = end - filepos; + long amount = end - (bufferOffset + pos); if (amount > Integer.MAX_VALUE) return Integer.MAX_VALUE; return (int) amount; @@ -584,41 +506,130 @@ public class ZipFile implements ZipConstants public int read() throws IOException { - if (filepos == end) + if (bufferOffset + pos >= end) return -1; - synchronized (raf) - { - raf.seek(filepos++); - return raf.read(); - } + if (pos == buffer.length) + { + bufferOffset += buffer.length; + pos = 0; + fillBuffer(); + } + return buffer[pos++] & 0xFF; } public int read(byte[] b, int off, int len) throws IOException { - if (len > end - filepos) + if (len > end - (bufferOffset + pos)) { - len = (int) (end - filepos); + len = (int) (end - (bufferOffset + pos)); if (len == 0) return -1; } - synchronized (raf) - { - raf.seek(filepos); - int count = raf.read(b, off, len); - if (count > 0) - filepos += len; - return count; - } + + int totalBytesRead = Math.min(buffer.length - pos, len); + System.arraycopy(buffer, pos, b, off, totalBytesRead); + pos += totalBytesRead; + off += totalBytesRead; + len -= totalBytesRead; + + while (len > 0) + { + bufferOffset += buffer.length; + pos = 0; + fillBuffer(); + int remain = Math.min(buffer.length, len); + System.arraycopy(buffer, pos, b, off, remain); + pos += remain; + off += remain; + len -= remain; + totalBytesRead += remain; + } + + return totalBytesRead; } - public long skip(long amount) + public long skip(long amount) throws IOException { if (amount < 0) - throw new IllegalArgumentException(); - if (amount > end - filepos) - amount = end - filepos; - filepos += amount; + return 0; + if (amount > end - (bufferOffset + pos)) + amount = end - (bufferOffset + pos); + seek(bufferOffset + pos + amount); return amount; } + + void seek(long newpos) throws IOException + { + long offset = newpos - bufferOffset; + if (offset >= 0 && offset <= buffer.length) + { + pos = (int) offset; + } + else + { + bufferOffset = newpos; + pos = 0; + fillBuffer(); + } + } + + void readFully(byte[] buf) throws IOException + { + if (read(buf, 0, buf.length) != buf.length) + throw new EOFException(); + } + + void readFully(byte[] buf, int off, int len) throws IOException + { + if (read(buf, off, len) != len) + throw new EOFException(); + } + + int readLeShort() throws IOException + { + int b0 = read(); + int b1 = read(); + if (b1 == -1) + throw new EOFException(); + return (b0 & 0xff) | (b1 & 0xff) << 8; + } + + int readLeInt() throws IOException + { + int b0 = read(); + int b1 = read(); + int b2 = read(); + int b3 = read(); + if (b3 == -1) + throw new EOFException(); + return ((b0 & 0xff) | (b1 & 0xff) << 8) + | ((b2 & 0xff) | (b3 & 0xff) << 8) << 16; + } + + String readString(int length) throws IOException + { + if (length > end - (bufferOffset + pos)) + throw new EOFException(); + + try + { + if (buffer.length - pos >= length) + { + String s = new String(buffer, pos, length, "UTF-8"); + pos += length; + return s; + } + else + { + byte[] b = new byte[length]; + readFully(b); + return new String(b, 0, length, "UTF-8"); + } + } + catch (UnsupportedEncodingException uee) + { + throw new AssertionError(uee); + } + } } } diff --git a/libjava/classpath/java/util/zip/ZipOutputStream.java b/libjava/classpath/java/util/zip/ZipOutputStream.java index 5c593b2..d292f7d 100644 --- a/libjava/classpath/java/util/zip/ZipOutputStream.java +++ b/libjava/classpath/java/util/zip/ZipOutputStream.java @@ -1,5 +1,5 @@ /* ZipOutputStream.java -- - Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -161,6 +161,16 @@ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstant } /** + * Write a long value as an int. Some of the zip constants + * are declared as longs even though they fit perfectly well + * into integers. + */ + private void writeLeInt(long value) throws IOException + { + writeLeInt((int) value); + } + + /** * Starts a new Zip entry. It automatically closes the previous * entry if present. If the compression method is stored, the entry * must have a valid size and crc, otherwise all elements (except -- cgit v1.1