11e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan/* 21e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * SingleXZInputStream 31e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 41e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Author: Lasse Collin <lasse.collin@tukaani.org> 51e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 61e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * This file has been put into the public domain. 71e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * You can do whatever you want with this file. 81e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 91e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 101e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanpackage org.tukaani.xz; 111e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 121e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport java.io.InputStream; 131e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport java.io.DataInputStream; 141e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport java.io.IOException; 151e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport java.io.EOFException; 161e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport org.tukaani.xz.common.DecoderUtil; 171e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport org.tukaani.xz.common.StreamFlags; 181e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport org.tukaani.xz.index.IndexHash; 191e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanimport org.tukaani.xz.check.Check; 201e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 211e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan/** 221e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Decompresses exactly one XZ Stream in streamed mode (no seeking). 231e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * The decompression stops after the first XZ Stream has been decompressed, 241e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * and the read position in the input stream is left at the first byte 251e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * after the end of the XZ Stream. This can be useful when XZ data has 261e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * been stored inside some other file format or protocol. 271e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <p> 281e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Unless you know what you are doing, don't use this class to decompress 291e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * standalone .xz files. For that purpose, use <code>XZInputStream</code>. 301e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 311e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <h4>When uncompressed size is known beforehand</h4> 321e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <p> 331e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * If you are decompressing complete XZ streams and your application knows 341e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * exactly how much uncompressed data there should be, it is good to try 351e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * reading one more byte by calling <code>read()</code> and checking 361e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * that it returns <code>-1</code>. This way the decompressor will parse the 371e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * file footers and verify the integrity checks, giving the caller more 381e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * confidence that the uncompressed data is valid. 391e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 401e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @see XZInputStream 411e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 421e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnanpublic class SingleXZInputStream extends InputStream { 431e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private InputStream in; 441e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private final int memoryLimit; 451e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private final StreamFlags streamHeaderFlags; 461e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private final Check check; 471e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private final boolean verifyCheck; 481e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private BlockInputStream blockDecoder = null; 491e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private final IndexHash indexHash = new IndexHash(); 501e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private boolean endReached = false; 511e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private IOException exception = null; 521e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 531e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private final byte[] tempBuf = new byte[1]; 541e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 551e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 561e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Reads the Stream Header into a buffer. 571e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * This is a helper function for the constructors. 581e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 591e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private static byte[] readStreamHeader(InputStream in) throws IOException { 601e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan byte[] streamHeader = new byte[DecoderUtil.STREAM_HEADER_SIZE]; 611e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan new DataInputStream(in).readFully(streamHeader); 621e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan return streamHeader; 631e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 641e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 651e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 661e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Creates a new XZ decompressor that decompresses exactly one 671e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * XZ Stream from <code>in</code> without a memory usage limit. 681e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <p> 691e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * This constructor reads and parses the XZ Stream Header (12 bytes) 701e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * from <code>in</code>. The header of the first Block is not read 711e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * until <code>read</code> is called. 721e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 731e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @param in input stream from which XZ-compressed 741e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * data is read 751e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 761e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws XZFormatException 771e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * input is not in the XZ format 781e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 791e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws CorruptedInputException 801e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * XZ header CRC32 doesn't match 811e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 821e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws UnsupportedOptionsException 831e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * XZ header is valid but specifies options 841e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * not supported by this implementation 851e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 861e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws EOFException 871e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * less than 12 bytes of input was available 881e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * from <code>in</code> 891e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 901e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws IOException may be thrown by <code>in</code> 911e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 921e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan public SingleXZInputStream(InputStream in) throws IOException { 931e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan this(in, -1); 941e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 951e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 961e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 971e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Creates a new XZ decompressor that decompresses exactly one 981e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * XZ Stream from <code>in</code> with an optional memory usage limit. 991e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <p> 1001e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * This is identical to <code>SingleXZInputStream(InputStream)</code> 1011e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * except that this takes also the <code>memoryLimit</code> argument. 1021e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1031e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @param in input stream from which XZ-compressed 1041e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * data is read 1051e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1061e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @param memoryLimit memory usage limit in kibibytes (KiB) 1071e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * or <code>-1</code> to impose no 1081e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * memory usage limit 1091e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1101e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws XZFormatException 1111e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * input is not in the XZ format 1121e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1131e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws CorruptedInputException 1141e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * XZ header CRC32 doesn't match 1151e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1161e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws UnsupportedOptionsException 1171e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * XZ header is valid but specifies options 1181e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * not supported by this implementation 1191e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1201e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws EOFException 1211e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * less than 12 bytes of input was available 1221e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * from <code>in</code> 1231e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1241e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws IOException may be thrown by <code>in</code> 1251e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 1261e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan public SingleXZInputStream(InputStream in, int memoryLimit) 1271e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan throws IOException { 1281e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan this(in, memoryLimit, true, readStreamHeader(in)); 1291e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 1301e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 1311e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 1321e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Creates a new XZ decompressor that decompresses exactly one 1331e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * XZ Stream from <code>in</code> with an optional memory usage limit 1341e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * and ability to disable verification of integrity checks. 1351e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <p> 1361e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * This is identical to <code>SingleXZInputStream(InputStream,int)</code> 1371e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * except that this takes also the <code>verifyCheck</code> argument. 1381e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <p> 1391e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Note that integrity check verification should almost never be disabled. 1401e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Possible reasons to disable integrity check verification: 1411e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <ul> 1421e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <li>Trying to recover data from a corrupt .xz file.</li> 1431e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <li>Speeding up decompression. This matters mostly with SHA-256 1441e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * or with files that have compressed extremely well. It's recommended 1451e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * that integrity checking isn't disabled for performance reasons 1461e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * unless the file integrity is verified externally in some other 1471e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * way.</li> 1481e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * </ul> 1491e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <p> 1501e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <code>verifyCheck</code> only affects the integrity check of 1511e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * the actual compressed data. The CRC32 fields in the headers 1521e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * are always verified. 1531e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1541e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @param in input stream from which XZ-compressed 1551e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * data is read 1561e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1571e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @param memoryLimit memory usage limit in kibibytes (KiB) 1581e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * or <code>-1</code> to impose no 1591e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * memory usage limit 1601e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1611e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @param verifyCheck if <code>true</code>, the integrity checks 1621e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * will be verified; this should almost never 1631e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * be set to <code>false</code> 1641e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1651e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws XZFormatException 1661e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * input is not in the XZ format 1671e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1681e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws CorruptedInputException 1691e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * XZ header CRC32 doesn't match 1701e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1711e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws UnsupportedOptionsException 1721e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * XZ header is valid but specifies options 1731e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * not supported by this implementation 1741e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1751e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws EOFException 1761e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * less than 12 bytes of input was available 1771e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * from <code>in</code> 1781e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1791e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws IOException may be thrown by <code>in</code> 1801e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 1811e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @since 1.6 1821e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 1831e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan public SingleXZInputStream(InputStream in, int memoryLimit, 1841e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan boolean verifyCheck) throws IOException { 1851e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan this(in, memoryLimit, verifyCheck, readStreamHeader(in)); 1861e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 1871e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 1881e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan SingleXZInputStream(InputStream in, int memoryLimit, boolean verifyCheck, 1891e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan byte[] streamHeader) throws IOException { 1901e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan this.in = in; 1911e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan this.memoryLimit = memoryLimit; 1921e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan this.verifyCheck = verifyCheck; 1931e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan streamHeaderFlags = DecoderUtil.decodeStreamHeader(streamHeader); 1941e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan check = Check.getInstance(streamHeaderFlags.checkType); 1951e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 1961e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 1971e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 1981e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Gets the ID of the integrity check used in this XZ Stream. 1991e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2001e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @return the Check ID specified in the XZ Stream Header 2011e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 2021e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan public int getCheckType() { 2031e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan return streamHeaderFlags.checkType; 2041e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 2051e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 2061e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 2071e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Gets the name of the integrity check used in this XZ Stream. 2081e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2091e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @return the name of the check specified in the XZ Stream Header 2101e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 2111e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan public String getCheckName() { 2121e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan return check.getName(); 2131e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 2141e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 2151e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 2161e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Decompresses the next byte from this input stream. 2171e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <p> 2181e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Reading lots of data with <code>read()</code> from this input stream 2191e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * may be inefficient. Wrap it in {@link java.io.BufferedInputStream} 2201e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * if you need to read lots of data one byte at a time. 2211e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2221e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @return the next decompressed byte, or <code>-1</code> 2231e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * to indicate the end of the compressed stream 2241e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2251e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws CorruptedInputException 2261e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws UnsupportedOptionsException 2271e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws MemoryLimitException 2281e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2291e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws XZIOException if the stream has been closed 2301e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2311e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws EOFException 2321e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * compressed input is truncated or corrupt 2331e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2341e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws IOException may be thrown by <code>in</code> 2351e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 2361e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan public int read() throws IOException { 2371e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan return read(tempBuf, 0, 1) == -1 ? -1 : (tempBuf[0] & 0xFF); 2381e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 2391e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 2401e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 2411e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Decompresses into an array of bytes. 2421e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <p> 2431e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * If <code>len</code> is zero, no bytes are read and <code>0</code> 2441e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * is returned. Otherwise this will try to decompress <code>len</code> 2451e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * bytes of uncompressed data. Less than <code>len</code> bytes may 2461e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * be read only in the following situations: 2471e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <ul> 2481e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <li>The end of the compressed data was reached successfully.</li> 2491e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <li>An error is detected after at least one but less <code>len</code> 2501e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * bytes have already been successfully decompressed. 2511e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * The next call with non-zero <code>len</code> will immediately 2521e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * throw the pending exception.</li> 2531e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * <li>An exception is thrown.</li> 2541e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * </ul> 2551e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2561e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @param buf target buffer for uncompressed data 2571e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @param off start offset in <code>buf</code> 2581e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @param len maximum number of uncompressed bytes to read 2591e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2601e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @return number of bytes read, or <code>-1</code> to indicate 2611e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * the end of the compressed stream 2621e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2631e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws CorruptedInputException 2641e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws UnsupportedOptionsException 2651e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws MemoryLimitException 2661e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2671e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws XZIOException if the stream has been closed 2681e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2691e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws EOFException 2701e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * compressed input is truncated or corrupt 2711e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 2721e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws IOException may be thrown by <code>in</code> 2731e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 2741e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan public int read(byte[] buf, int off, int len) throws IOException { 2751e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (off < 0 || len < 0 || off + len < 0 || off + len > buf.length) 2761e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan throw new IndexOutOfBoundsException(); 2771e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 2781e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (len == 0) 2791e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan return 0; 2801e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 2811e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (in == null) 2821e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan throw new XZIOException("Stream closed"); 2831e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 2841e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (exception != null) 2851e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan throw exception; 2861e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 2871e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (endReached) 2881e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan return -1; 2891e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 2901e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan int size = 0; 2911e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 2921e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan try { 2931e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan while (len > 0) { 2941e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (blockDecoder == null) { 2951e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan try { 2961e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan blockDecoder = new BlockInputStream( 2971e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan in, check, verifyCheck, memoryLimit, -1, -1); 2981e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } catch (IndexIndicatorException e) { 2991e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan indexHash.validate(in); 3001e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan validateStreamFooter(); 3011e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan endReached = true; 3021e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan return size > 0 ? size : -1; 3031e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3041e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3051e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 3061e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan int ret = blockDecoder.read(buf, off, len); 3071e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 3081e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (ret > 0) { 3091e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan size += ret; 3101e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan off += ret; 3111e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan len -= ret; 3121e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } else if (ret == -1) { 3131e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan indexHash.add(blockDecoder.getUnpaddedSize(), 3141e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan blockDecoder.getUncompressedSize()); 3151e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan blockDecoder = null; 3161e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3171e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3181e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } catch (IOException e) { 3191e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan exception = e; 3201e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (size == 0) 3211e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan throw e; 3221e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3231e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 3241e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan return size; 3251e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3261e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 3271e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan private void validateStreamFooter() throws IOException { 3281e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan byte[] buf = new byte[DecoderUtil.STREAM_HEADER_SIZE]; 3291e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan new DataInputStream(in).readFully(buf); 3301e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan StreamFlags streamFooterFlags = DecoderUtil.decodeStreamFooter(buf); 3311e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 3321e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (!DecoderUtil.areStreamFlagsEqual(streamHeaderFlags, 3331e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan streamFooterFlags) 3341e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan || indexHash.getIndexSize() != streamFooterFlags.backwardSize) 3351e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan throw new CorruptedInputException( 3361e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan "XZ Stream Footer does not match Stream Header"); 3371e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3381e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 3391e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 3401e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Returns the number of uncompressed bytes that can be read 3411e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * without blocking. The value is returned with an assumption 3421e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * that the compressed input data will be valid. If the compressed 3431e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * data is corrupt, <code>CorruptedInputException</code> may get 3441e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * thrown before the number of bytes claimed to be available have 3451e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * been read from this input stream. 3461e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 3471e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @return the number of uncompressed bytes that can be read 3481e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * without blocking 3491e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 3501e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan public int available() throws IOException { 3511e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (in == null) 3521e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan throw new XZIOException("Stream closed"); 3531e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 3541e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (exception != null) 3551e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan throw exception; 3561e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 3571e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan return blockDecoder == null ? 0 : blockDecoder.available(); 3581e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3591e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan 3601e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan /** 3611e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * Closes the stream and calls <code>in.close()</code>. 3621e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * If the stream was already closed, this does nothing. 3631e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * 3641e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan * @throws IOException if thrown by <code>in.close()</code> 3651e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan */ 3661e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan public void close() throws IOException { 3671e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan if (in != null) { 3681e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan try { 3691e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan in.close(); 3701e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } finally { 3711e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan in = null; 3721e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3731e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3741e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan } 3751e977d75f657dacb4cb5c36ab6054bcf66b08076Vinod Krishnan} 376