CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/ext/libzip/zip_algorithm_deflate.c
Views: 1401
/*1zip_algorithm_deflate.c -- deflate (de)compression routines2Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner34This file is part of libzip, a library to manipulate ZIP archives.5The authors can be contacted at <[email protected]>67Redistribution and use in source and binary forms, with or without8modification, are permitted provided that the following conditions9are met:101. Redistributions of source code must retain the above copyright11notice, this list of conditions and the following disclaimer.122. Redistributions in binary form must reproduce the above copyright13notice, this list of conditions and the following disclaimer in14the documentation and/or other materials provided with the15distribution.163. The names of the authors may not be used to endorse or promote17products derived from this software without specific prior18written permission.1920THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS21OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED22WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY24DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE26GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS27INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER28IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR29OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.31*/3233#include "zipint.h"3435#include <limits.h>36#include <stdlib.h>37#include <zlib.h>3839struct ctx {40zip_error_t *error;41bool compress;42int compression_flags;43bool end_of_input;44z_stream zstr;45};464748static void *49allocate(bool compress, int compression_flags, zip_error_t *error) {50struct ctx *ctx;5152if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {53zip_error_set(error, ZIP_ET_SYS, errno);54return NULL;55}5657ctx->error = error;58ctx->compress = compress;59ctx->compression_flags = compression_flags;60if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {61ctx->compression_flags = Z_BEST_COMPRESSION;62}63ctx->end_of_input = false;6465ctx->zstr.zalloc = Z_NULL;66ctx->zstr.zfree = Z_NULL;67ctx->zstr.opaque = NULL;6869return ctx;70}717273static void *74compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {75return allocate(true, compression_flags, error);76}777879static void *80decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {81return allocate(false, compression_flags, error);82}838485static void86deallocate(void *ud) {87struct ctx *ctx = (struct ctx *)ud;8889free(ctx);90}919293static zip_uint16_t94general_purpose_bit_flags(void *ud) {95struct ctx *ctx = (struct ctx *)ud;9697if (!ctx->compress) {98return 0;99}100101if (ctx->compression_flags < 3) {102return 2 << 1;103}104else if (ctx->compression_flags > 7) {105return 1 << 1;106}107return 0;108}109110111static bool112start(void *ud) {113struct ctx *ctx = (struct ctx *)ud;114int ret;115116ctx->zstr.avail_in = 0;117ctx->zstr.next_in = NULL;118ctx->zstr.avail_out = 0;119ctx->zstr.next_out = NULL;120121if (ctx->compress) {122/* negative value to tell zlib not to write a header */123ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);124}125else {126ret = inflateInit2(&ctx->zstr, -MAX_WBITS);127}128129if (ret != Z_OK) {130zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);131return false;132}133134135return true;136}137138139static bool140end(void *ud) {141struct ctx *ctx = (struct ctx *)ud;142int err;143144if (ctx->compress) {145err = deflateEnd(&ctx->zstr);146}147else {148err = inflateEnd(&ctx->zstr);149}150151if (err != Z_OK) {152zip_error_set(ctx->error, ZIP_ER_ZLIB, err);153return false;154}155156return true;157}158159160static bool161input(void *ud, zip_uint8_t *data, zip_uint64_t length) {162struct ctx *ctx = (struct ctx *)ud;163164if (length > UINT_MAX || ctx->zstr.avail_in > 0) {165zip_error_set(ctx->error, ZIP_ER_INVAL, 0);166return false;167}168169ctx->zstr.avail_in = (uInt)length;170ctx->zstr.next_in = (Bytef *)data;171172return true;173}174175176static void177end_of_input(void *ud) {178struct ctx *ctx = (struct ctx *)ud;179180ctx->end_of_input = true;181}182183184static zip_compression_status_t185process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {186struct ctx *ctx = (struct ctx *)ud;187188int ret;189190ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);191ctx->zstr.next_out = (Bytef *)data;192193if (ctx->compress) {194ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);195}196else {197ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);198}199200*length = *length - ctx->zstr.avail_out;201202switch (ret) {203case Z_OK:204return ZIP_COMPRESSION_OK;205206case Z_STREAM_END:207return ZIP_COMPRESSION_END;208209case Z_BUF_ERROR:210if (ctx->zstr.avail_in == 0) {211return ZIP_COMPRESSION_NEED_DATA;212}213214/* fallthrough */215216default:217zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);218return ZIP_COMPRESSION_ERROR;219}220}221222/* clang-format off */223224zip_compression_algorithm_t zip_algorithm_deflate_compress = {225compress_allocate,226deallocate,227general_purpose_bit_flags,22820,229start,230end,231input,232end_of_input,233process234};235236237zip_compression_algorithm_t zip_algorithm_deflate_decompress = {238decompress_allocate,239deallocate,240general_purpose_bit_flags,24120,242start,243end,244input,245end_of_input,246process247};248249/* clang-format on */250251252