source_result::status drive(bool flush = false) { if (empty()) return source_result::eos; int deflate_flags = flush ? MZ_SYNC_FLUSH : MZ_NO_FLUSH; while (true) { if (str.avail_in == 0 && pull) { cur_ = end_; auto s = next_piece_(); if (s == source_result::ok) { str.avail_in = (unsigned int)buf_left(); sassert(str.avail_in > 0); str.next_in = (unsigned char*)cur_; } else if (s != source_result::eos) { return s; } } if (str.avail_out == 0) { cur_out->size_ = str.next_out - cur_out->data; return source_result::ok; } int ret; if (compress) ret = mz_deflate(&str, deflate_flags); else ret = mz_inflate(&str, deflate_flags); if (ret == MZ_STREAM_END) { cur_out->size_ = str.next_out - cur_out->data; close(); return source_result::ok; } else if (ret != MZ_OK) { throw std::runtime_error("Error while deflating"); } else if (deflate_flags == MZ_SYNC_FLUSH && str.avail_in == 0) { cur_out->size_ = str.next_out - cur_out->data; return source_result::ok; } } }
DataBuffer ZLibCompression::compress(const DataBuffer &data, bool raw, int compression_level, CompressionMode mode) { const int window_bits = 15; DataBuffer zbuffer(1024*1024); IODevice_Memory output; int strategy = MZ_DEFAULT_STRATEGY; switch (mode) { case default_strategy: strategy = MZ_DEFAULT_STRATEGY; break; case filtered: strategy = MZ_FILTERED; break; case huffman_only: strategy = MZ_HUFFMAN_ONLY; break; case rle: strategy = MZ_RLE; break; case fixed: strategy = MZ_FIXED; break; } mz_stream zs = { nullptr }; int result = mz_deflateInit2(&zs, compression_level, MZ_DEFLATED, raw ? -window_bits : window_bits, 8, strategy); // Undocumented: if wbits is negative, zlib skips header check if (result != MZ_OK) throw Exception("Zlib deflateInit failed"); try { zs.next_in = (unsigned char *) data.get_data(); zs.avail_in = data.get_size(); while (true) { zs.next_out = (unsigned char *) zbuffer.get_data(); zs.avail_out = zbuffer.get_size(); int result = mz_deflate(&zs, MZ_FINISH); if (result == MZ_NEED_DICT) throw Exception("Zlib deflate wants a dictionary!"); if (result == MZ_DATA_ERROR) throw Exception("Zip data stream is corrupted"); if (result == MZ_STREAM_ERROR) throw Exception("Zip stream structure was inconsistent!"); if (result == MZ_MEM_ERROR) throw Exception("Zlib did not have enough memory to compress file!"); if (result == MZ_BUF_ERROR) throw Exception("Not enough data in buffer when Z_FINISH was used"); if (result != MZ_OK && result != MZ_STREAM_END) throw Exception("Zlib deflate failed while compressing zip file!"); int zsize = zbuffer.get_size() - zs.avail_out; if (zsize == 0) break; output.write(zbuffer.get_data(), zsize); if (result == MZ_STREAM_END) break; } mz_deflateEnd(&zs); } catch (...) { mz_deflateEnd(&zs); throw; } return output.get_data(); }
void ZipWriter::end_file() { if (!impl->file_begun) return; if (impl->compress) { impl->zs.next_in = nullptr; impl->zs.avail_in = 0; while (true) { impl->zs.next_out = (unsigned char *)impl->zbuffer; impl->zs.avail_out = 16 * 1024; int result = mz_deflate(&impl->zs, MZ_FINISH); if (result == MZ_NEED_DICT) throw Exception("Zlib deflate wants a dictionary!"); if (result == MZ_DATA_ERROR) throw Exception("Zip data stream is corrupted"); if (result == MZ_STREAM_ERROR) throw Exception("Zip stream structure was inconsistent!"); if (result == MZ_MEM_ERROR) throw Exception("Zlib did not have enough memory to compress file!"); if (result == MZ_BUF_ERROR) throw Exception("Not enough data in buffer when Z_FINISH was used"); if (result != MZ_OK && result != MZ_STREAM_END) throw Exception("Zlib deflate failed while compressing zip file!"); int64_t zsize = 16 * 1024 - impl->zs.avail_out; if (zsize == 0) break; impl->output.write(impl->zbuffer, zsize); impl->compressed_length += zsize; if (result == MZ_STREAM_END) break; } mz_deflateEnd(&impl->zs); impl->compress = false; } impl->local_header.uncompressed_size = impl->uncompressed_length; impl->local_header.compressed_size = impl->compressed_length; impl->local_header.crc32 = ZipArchive_Impl::calc_crc32(nullptr, 0, impl->crc32, true); int64_t current_offset = impl->output.get_position(); impl->output.seek(impl->local_header_offset); impl->local_header.save(impl->output); impl->output.seek(current_offset); ZipWriter_Impl::FileEntry file_entry; file_entry.local_header = impl->local_header; file_entry.local_header_offset = impl->local_header_offset; impl->written_files.push_back(file_entry); impl->file_begun = false; }
static int lmz_inflator_deflator_impl(lua_State* L, lmz_stream_t* stream) { mz_streamp miniz_stream = &(stream->stream); size_t data_size; const char* data = luaL_checklstring(L, 2, &data_size); int flush = luaL_checkoption(L, 3, "no", flush_types); miniz_stream->avail_in = data_size; miniz_stream->next_in = (const unsigned char*)data; luaL_Buffer buf; luaL_buffinit(L, &buf); while (1) { char* buffer = luaL_prepbuffer(&buf); memset(buffer, 0, LUAL_BUFFERSIZE); miniz_stream->avail_out = LUAL_BUFFERSIZE; miniz_stream->next_out = (unsigned char*)buffer; size_t before = miniz_stream->total_out; int status; if (stream->mode) { status = mz_inflate(miniz_stream, flush); } else { status = mz_deflate(miniz_stream, flush); } size_t added = miniz_stream->total_out - before; luaL_addsize(&buf, added); switch (status) { case MZ_OK: case MZ_STREAM_END: luaL_pushresult(&buf); return 1; case MZ_STREAM_ERROR: case MZ_DATA_ERROR: case MZ_PARAM_ERROR: luaL_pushresult(&buf); lua_pushnil(L); lua_insert(L, -2); lua_pushstring(L, mz_error(status)); lua_insert(L, -2); return 3; case MZ_BUF_ERROR: if (stream->mode) { // not enough input luaL_pushresult(&buf); lua_pushnil(L); lua_insert(L, -2); lua_pushstring(L, "Not enough input data"); lua_insert(L, -2); return 3; } break; } } }
St go (int level /* Zip level; 0 to mean unzip */, int ifd, int ofd) { uint8_t x[chunkSize], y[chunkSize]; z_stream s; memset (&s, 0, sizeof (z_stream)); int windowBits = -MZ_DEFAULT_WINDOW_BITS; if (level == 0 ? inflateInit2 (&s, windowBits) : deflateInit2 (&s, level, MZ_DEFLATED, windowBits, 6, MZ_DEFAULT_STRATEGY)) { errx (-1, "failed"); } for (;;) { int n, fin = 0; n = read (ifd, x + s.avail_in, chunkSize - s.avail_in); if (n < 0) err (n, "failed to read"); s.next_in = x; s.next_out = y; s.avail_in += n; s.avail_out = chunkSize; retry: switch (level == 0 ? mz_inflate (&s, MZ_SYNC_FLUSH) : mz_deflate (&s, n > 0 ? MZ_FINISH : MZ_SYNC_FLUSH)) { int n; case MZ_STREAM_END: fin = 1; case MZ_OK: write (ofd, y, chunkSize - s.avail_out); s.avail_in = 0; if (fin) return (St) { .l = level == 0 ? s.total_out : s.total_in, .crc32 = s.crc32 }; break; case MZ_BUF_ERROR: continue; case MZ_DATA_ERROR: errx (-1, "not flated data"); case MZ_PARAM_ERROR: errx (-1, "failed"); } } } ssize_t readn (int fd, void *x, size_t n) { int n0 = n; while (n > 0) { int m = read (fd, x, n); if (m < 0) return m; n -= m; x = (uint8_t *)x + m; } return n0; }
void ZipWriter::write_file_data(const void *data, int64_t size) { if (!impl->file_begun) throw Exception("ZipWriter::begin_file not called prior ZipWriter::write_file_data"); impl->uncompressed_length += size; if (impl->compress) { impl->zs.next_in = (unsigned char *)data; impl->zs.avail_in = size; while (impl->zs.avail_in > 0) { impl->zs.next_out = (unsigned char *)impl->zbuffer; impl->zs.avail_out = 16 * 1024; int result = mz_deflate(&impl->zs, MZ_NO_FLUSH); if (result == MZ_NEED_DICT) throw Exception("Zlib deflate wants a dictionary!"); if (result == MZ_DATA_ERROR) throw Exception("Zip data stream is corrupted"); if (result == MZ_STREAM_ERROR) throw Exception("Zip stream structure was inconsistent!"); if (result == MZ_MEM_ERROR) throw Exception("Zlib did not have enough memory to compress file!"); if (result == MZ_BUF_ERROR) throw Exception("Not enough data in buffer when Z_FINISH was used"); if (result != MZ_OK) throw Exception("Zlib deflate failed while compressing zip file!"); int64_t zsize = 16 * 1024 - impl->zs.avail_out; if (zsize > 0) { impl->compressed_length += zsize; impl->output.write(impl->zbuffer, zsize); } } } else { impl->compressed_length += size; impl->output.write(data, size); } impl->crc32 = ZipArchive_Impl::calc_crc32(data, size, impl->crc32, false); }