chunk_reader::pointer chunk_reader::get(slice_reader & base, const chunk & chunk) { if(!base.seek(chunk.first_slice, chunk.offset)) { throw chunk_error("error seeking"); } char magic[ARRAY_SIZE(chunk_id)]; if(base.read(magic, 4) != 4 || memcmp(magic, chunk_id, ARRAY_SIZE(chunk_id))) { throw chunk_error("bad chunk magic"); } pointer result = boost::make_shared<type>(); switch(chunk.compression) { case Stored: break; case Zlib: result->push(io::zlib_decompressor(), 8192); break; case BZip2: result->push(io::bzip2_decompressor(), 8192); break; #ifdef HAVE_LZMA case LZMA1: result->push(inno_lzma1_decompressor(), 8192); break; case LZMA2: result->push(inno_lzma2_decompressor(), 8192); break; #else case LZMA1: case LZMA2: throw chunk_error("LZMA decompression not supported by this Inno Extract build"); #endif default: throw chunk_error("unknown compression"); } result->push(io::restrict(boost::ref(base), 0, int64_t(chunk.size))); return result; }
block_reader::pointer block_reader::get(std::istream & base, const setup::version & version) { USE_ENUM_NAMES(block_compression) uint32_t expected_checksum = load_number<uint32_t>(base); crypto::crc32 actual_checksum; actual_checksum.init(); uint32_t stored_size; block_compression compression; if(version >= INNO_VERSION(4, 0, 9)) { stored_size = actual_checksum.load_number<uint32_t>(base); uint8_t compressed = actual_checksum.load_number<uint8_t>(base); compression = compressed ? (version >= INNO_VERSION(4, 1, 6) ? LZMA1 : Zlib) : Stored; } else { uint32_t compressed_size = actual_checksum.load_number<uint32_t>(base); uint32_t uncompressed_size = actual_checksum.load_number<uint32_t>(base); if(compressed_size == uint32_t(-1)) { stored_size = uncompressed_size, compression = Stored; } else { stored_size = compressed_size, compression = Zlib; } // Add the size of a CRC32 checksum for each 4KiB subblock. stored_size += uint32_t(ceildiv<uint64_t>(stored_size, 4096) * 4); } if(actual_checksum.finalize() != expected_checksum) { throw block_error("block CRC32 mismatch"); } debug("[block] size: " << stored_size << " compression: " << compression); boost::shared_ptr<io::filtering_istream> fis = boost::make_shared<io::filtering_istream>(); switch(compression) { case Stored: break; case Zlib: fis->push(io::zlib_decompressor(), 8192); break; #if INNOEXTRACT_HAVE_LZMA case LZMA1: fis->push(inno_lzma1_decompressor(), 8192); break; #else case LZMA1: throw block_error("LZMA decompression not supported by this " + std::string(innoextract_name) + " build"); #endif } fis->push(inno_block_filter(), 4096); fis->push(io::restrict(base, 0, stored_size)); return fis; }