1 /* GZIPInputStream.java - Input filter for reading gzip file
2 Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package java.util.zip;
40 import java.io.InputStream;
41 import java.io.IOException;
44 * This filter stream is used to decompress a "GZIP" format stream.
45 * The "GZIP" format is described in RFC 1952.
51 public class GZIPInputStream
52 extends InflaterInputStream
55 * The magic number found at the start of a GZIP stream.
57 public static final int GZIP_MAGIC = 0x8b1f;
59 static final int Z_DEFLATED = 8;
62 * The mask for bit 1 of the flag byte.
64 static final int HEAD_CRC = 0x02;
67 * The mask for bit 2 of the flag byte.
69 static final int EXTRA_FIELD = 0x04;
72 * The mask for bit 3 of the flag byte.
74 static final int ORIG_NAME = 0x08;
77 * The mask for bit 4 of the flag byte.
79 static final int COMMENT = 0x10;
82 * The mask for all reserved bits of the flag byte.
84 static final int RESERVED = 0xe0;
87 * The CRC-32 checksum value for uncompressed data.
92 * Indicates whether or not the end of the stream has been reached.
94 protected boolean eos;
97 * Creates a GZIPInputStream with the default buffer size.
99 * @param in The stream to read compressed data from
102 * @throws IOException if an error occurs during an I/O operation.
104 public GZIPInputStream(InputStream in)
111 * Creates a GZIPInputStream with the specified buffer size.
113 * @param in The stream to read compressed data from
115 * @param size The size of the buffer to use.
117 * @throws IOException if an error occurs during an I/O operation.
118 * @throws IllegalArgumentException if <code>size</code>
119 * is less than or equal to 0.
121 public GZIPInputStream(InputStream in, int size)
124 super(in, new Inflater(true), size);
126 // NOTE: header reading code taken from zlib's gzio.c.
128 // Read the magic number.
129 int magic = eof_read() | (eof_read() << 8);
130 if (magic != GZIP_MAGIC)
131 throw new ZipException("gzip header corrupted");
133 int method = eof_read();
134 int flags = eof_read();
136 if (method != Z_DEFLATED || (flags & RESERVED) != 0)
137 throw new ZipException("gzip header corrupted");
139 // Discard time, xflags, OS code.
140 for (int i = 0; i < 6; ++i)
143 // Skip the extra field.
144 if ((flags & EXTRA_FIELD) != 0)
146 int len = eof_read() | (eof_read() << 8);
151 if ((flags & ORIG_NAME) != 0)
161 if ((flags & COMMENT) != 0)
171 if ((flags & HEAD_CRC) != 0)
173 // FIXME: consider checking CRC of the header.
182 * Closes the input stream.
184 * @throws IOException if an error occurs during an I/O operation.
189 // Nothing to do here.
193 private final int eof_read() throws IOException
197 throw new ZipException("gzip header corrupted");
202 * Reads in GZIP-compressed data and stores it in uncompressed form
203 * into an array of bytes. The method will block until either
204 * enough input data becomes available or the compressed stream
207 * @param buf the buffer into which the uncompressed data will
209 * @param offset the offset indicating where in <code>buf</code>
210 * the uncompressed data should be placed.
211 * @param len the number of uncompressed bytes to be read.
213 public int read(byte[] buf, int offset, int len) throws IOException
217 int r = super.read(buf, offset, len);
222 byte[] tmp = new byte[8];
223 // First copy remaining bytes from inflater input buffer.
224 int avail = inf.getRemaining();
225 System.arraycopy(this.buf, this.len - avail, tmp, 0, avail);
227 // Now read remaining bytes from wrapped input stream.
228 for (int i = avail; i < 8; ++i)
230 tmp[i] = (byte) eof_read();
233 int header_crc = read4(tmp, 0);
234 if (crc.getValue() != header_crc)
235 throw new ZipException("corrupted gzip file - crc mismatch");
236 int isize = read4(tmp, 4);
237 if (inf.getTotalOut() != isize)
238 throw new ZipException("corrupted gzip file - size mismatch");
241 crc.update(buf, offset, r);
245 private final int read4(byte[] buf, int offset) throws IOException
247 return (((buf[offset + 3] & 0xFF) << 24) + ((buf[offset + 2] & 0xFF) << 16)
248 + ((buf[offset + 1] & 0xFF) << 8) + (buf[offset] & 0xFF));