| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,374 @@ | ||
| /* mz_strm_bzip.c -- Stream for bzip inflate/deflate | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
|
|
||
| #include "mz.h" | ||
| #include "mz_strm.h" | ||
| #include "mz_strm_bzip.h" | ||
|
|
||
| #include "bzlib.h" | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static mz_stream_vtbl mz_stream_bzip_vtbl = { | ||
| mz_stream_bzip_open, | ||
| mz_stream_bzip_is_open, | ||
| mz_stream_bzip_read, | ||
| mz_stream_bzip_write, | ||
| mz_stream_bzip_tell, | ||
| mz_stream_bzip_seek, | ||
| mz_stream_bzip_close, | ||
| mz_stream_bzip_error, | ||
| mz_stream_bzip_create, | ||
| mz_stream_bzip_delete, | ||
| mz_stream_bzip_get_prop_int64, | ||
| mz_stream_bzip_set_prop_int64 | ||
| }; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| typedef struct mz_stream_bzip_s { | ||
| mz_stream stream; | ||
| bz_stream bzstream; | ||
| int32_t mode; | ||
| int32_t error; | ||
| uint8_t buffer[INT16_MAX]; | ||
| int32_t buffer_len; | ||
| int16_t stream_end; | ||
| int64_t total_in; | ||
| int64_t total_out; | ||
| int64_t max_total_in; | ||
| int8_t initialized; | ||
| int16_t level; | ||
| } mz_stream_bzip; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_bzip_open(void *stream, const char *path, int32_t mode) { | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
|
|
||
| MZ_UNUSED(path); | ||
|
|
||
| bzip->bzstream.bzalloc = 0; | ||
| bzip->bzstream.bzfree = 0; | ||
| bzip->bzstream.opaque = 0; | ||
| bzip->bzstream.total_in_lo32 = 0; | ||
| bzip->bzstream.total_in_hi32 = 0; | ||
| bzip->bzstream.total_out_lo32 = 0; | ||
| bzip->bzstream.total_out_hi32 = 0; | ||
|
|
||
| bzip->total_in = 0; | ||
| bzip->total_out = 0; | ||
|
|
||
| if (mode & MZ_OPEN_MODE_WRITE) { | ||
| #ifdef MZ_ZIP_NO_COMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| bzip->bzstream.next_out = (char *)bzip->buffer; | ||
| bzip->bzstream.avail_out = sizeof(bzip->buffer); | ||
|
|
||
| bzip->error = BZ2_bzCompressInit(&bzip->bzstream, bzip->level, 0, 0); | ||
| #endif | ||
| } else if (mode & MZ_OPEN_MODE_READ) { | ||
| #ifdef MZ_ZIP_NO_DECOMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| bzip->bzstream.next_in = (char *)bzip->buffer; | ||
| bzip->bzstream.avail_in = 0; | ||
|
|
||
| bzip->error = BZ2_bzDecompressInit(&bzip->bzstream, 0, 0); | ||
| #endif | ||
| } | ||
|
|
||
| if (bzip->error != BZ_OK) | ||
| return MZ_OPEN_ERROR; | ||
|
|
||
| bzip->initialized = 1; | ||
| bzip->stream_end = 0; | ||
| bzip->mode = mode; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_bzip_is_open(void *stream) { | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
| if (bzip->initialized != 1) | ||
| return MZ_OPEN_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_bzip_read(void *stream, void *buf, int32_t size) { | ||
| #ifdef MZ_ZIP_NO_DECOMPRESSION | ||
| MZ_UNUSED(stream); | ||
| MZ_UNUSED(buf); | ||
| MZ_UNUSED(size); | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
| uint64_t total_in_before = 0; | ||
| uint64_t total_out_before = 0; | ||
| uint64_t total_in_after = 0; | ||
| uint64_t total_out_after = 0; | ||
| int32_t total_in = 0; | ||
| int32_t total_out = 0; | ||
| int32_t in_bytes = 0; | ||
| int32_t out_bytes = 0; | ||
| int32_t bytes_to_read = sizeof(bzip->buffer); | ||
| int32_t read = 0; | ||
| int32_t err = BZ_OK; | ||
|
|
||
|
|
||
| if (bzip->stream_end) | ||
| return 0; | ||
|
|
||
| bzip->bzstream.next_out = (char *)buf; | ||
| bzip->bzstream.avail_out = (unsigned int)size; | ||
|
|
||
| do { | ||
| if (bzip->bzstream.avail_in == 0) { | ||
| if (bzip->max_total_in > 0) { | ||
| if ((int64_t)bytes_to_read > (bzip->max_total_in - bzip->total_in)) | ||
| bytes_to_read = (int32_t)(bzip->max_total_in - bzip->total_in); | ||
| } | ||
|
|
||
| read = mz_stream_read(bzip->stream.base, bzip->buffer, bytes_to_read); | ||
|
|
||
| if (read < 0) | ||
| return read; | ||
|
|
||
| bzip->bzstream.next_in = (char *)bzip->buffer; | ||
| bzip->bzstream.avail_in = (uint32_t)read; | ||
| } | ||
|
|
||
| total_in_before = bzip->bzstream.avail_in; | ||
| total_out_before = bzip->bzstream.total_out_lo32 + | ||
| (((uint64_t)bzip->bzstream.total_out_hi32) << 32); | ||
|
|
||
| err = BZ2_bzDecompress(&bzip->bzstream); | ||
|
|
||
| total_in_after = bzip->bzstream.avail_in; | ||
| total_out_after = bzip->bzstream.total_out_lo32 + | ||
| (((uint64_t)bzip->bzstream.total_out_hi32) << 32); | ||
|
|
||
| in_bytes = (int32_t)(total_in_before - total_in_after); | ||
| out_bytes = (int32_t)(total_out_after - total_out_before); | ||
|
|
||
| total_in += in_bytes; | ||
| total_out += out_bytes; | ||
|
|
||
| bzip->total_in += in_bytes; | ||
| bzip->total_out += out_bytes; | ||
|
|
||
| if (err == BZ_STREAM_END) { | ||
| bzip->stream_end = 1; | ||
| break; | ||
| } | ||
| if (err != BZ_OK && err != BZ_RUN_OK) { | ||
| bzip->error = err; | ||
| break; | ||
| } | ||
| } while (bzip->bzstream.avail_out > 0); | ||
|
|
||
| if (bzip->error != 0) | ||
| return MZ_DATA_ERROR; | ||
|
|
||
| return total_out; | ||
| #endif | ||
| } | ||
|
|
||
| #ifndef MZ_ZIP_NO_COMPRESSION | ||
| static int32_t mz_stream_bzip_flush(void *stream) { | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
| if (mz_stream_write(bzip->stream.base, bzip->buffer, bzip->buffer_len) != bzip->buffer_len) | ||
| return MZ_WRITE_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| static int32_t mz_stream_bzip_compress(void *stream, int flush) { | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
| uint64_t total_out_before = 0; | ||
| uint64_t total_out_after = 0; | ||
| uint32_t out_bytes = 0; | ||
| int32_t err = BZ_OK; | ||
|
|
||
| do { | ||
| if (bzip->bzstream.avail_out == 0) { | ||
| err = mz_stream_bzip_flush(bzip); | ||
| if (err != MZ_OK) | ||
| return err; | ||
|
|
||
| bzip->bzstream.avail_out = sizeof(bzip->buffer); | ||
| bzip->bzstream.next_out = (char *)bzip->buffer; | ||
|
|
||
| bzip->buffer_len = 0; | ||
| } | ||
|
|
||
| total_out_before = bzip->bzstream.total_out_lo32 + | ||
| (((uint64_t)bzip->bzstream.total_out_hi32) << 32); | ||
|
|
||
| err = BZ2_bzCompress(&bzip->bzstream, flush); | ||
|
|
||
| total_out_after = bzip->bzstream.total_out_lo32 + | ||
| (((uint64_t)bzip->bzstream.total_out_hi32) << 32); | ||
|
|
||
| out_bytes = (uint32_t)(total_out_after - total_out_before); | ||
|
|
||
| bzip->buffer_len += out_bytes; | ||
| bzip->total_out += out_bytes; | ||
|
|
||
| if (err == BZ_STREAM_END) | ||
| break; | ||
| if (err < 0) { | ||
| bzip->error = err; | ||
| return MZ_DATA_ERROR; | ||
| } | ||
| } while ((bzip->bzstream.avail_in > 0) || (flush == BZ_FINISH && err == BZ_FINISH_OK)); | ||
|
|
||
| return MZ_OK; | ||
| } | ||
| #endif | ||
|
|
||
| int32_t mz_stream_bzip_write(void *stream, const void *buf, int32_t size) { | ||
| #ifdef MZ_ZIP_NO_COMPRESSION | ||
| MZ_UNUSED(stream); | ||
| MZ_UNUSED(buf); | ||
| MZ_UNUSED(size); | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
| int32_t err = MZ_OK; | ||
|
|
||
| bzip->bzstream.next_in = (char *)(intptr_t)buf; | ||
| bzip->bzstream.avail_in = (unsigned int)size; | ||
|
|
||
| err = mz_stream_bzip_compress(stream, BZ_RUN); | ||
| if (err != MZ_OK) { | ||
| return err; | ||
| } | ||
|
|
||
| bzip->total_in += size; | ||
| return size; | ||
| #endif | ||
| } | ||
|
|
||
| int64_t mz_stream_bzip_tell(void *stream) { | ||
| MZ_UNUSED(stream); | ||
|
|
||
| return MZ_TELL_ERROR; | ||
| } | ||
|
|
||
| int32_t mz_stream_bzip_seek(void *stream, int64_t offset, int32_t origin) { | ||
| MZ_UNUSED(stream); | ||
| MZ_UNUSED(offset); | ||
| MZ_UNUSED(origin); | ||
|
|
||
| return MZ_SEEK_ERROR; | ||
| } | ||
|
|
||
| int32_t mz_stream_bzip_close(void *stream) { | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
|
|
||
| if (bzip->mode & MZ_OPEN_MODE_WRITE) { | ||
| #ifdef MZ_ZIP_NO_COMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| mz_stream_bzip_compress(stream, BZ_FINISH); | ||
| mz_stream_bzip_flush(stream); | ||
|
|
||
| BZ2_bzCompressEnd(&bzip->bzstream); | ||
| #endif | ||
| } else if (bzip->mode & MZ_OPEN_MODE_READ) { | ||
| #ifdef MZ_ZIP_NO_DECOMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| BZ2_bzDecompressEnd(&bzip->bzstream); | ||
| #endif | ||
| } | ||
|
|
||
| bzip->initialized = 0; | ||
|
|
||
| if (bzip->error != BZ_OK) | ||
| return MZ_CLOSE_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_bzip_error(void *stream) { | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
| return bzip->error; | ||
| } | ||
|
|
||
| int32_t mz_stream_bzip_get_prop_int64(void *stream, int32_t prop, int64_t *value) { | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_TOTAL_IN: | ||
| *value = bzip->total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| *value = bzip->max_total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_OUT: | ||
| *value = bzip->total_out; | ||
| break; | ||
| case MZ_STREAM_PROP_HEADER_SIZE: | ||
| *value = 0; | ||
| break; | ||
| default: | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_bzip_set_prop_int64(void *stream, int32_t prop, int64_t value) { | ||
| mz_stream_bzip *bzip = (mz_stream_bzip *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_COMPRESS_LEVEL: | ||
| if (value < 0) | ||
| bzip->level = 6; | ||
| else | ||
| bzip->level = (int16_t)value; | ||
| return MZ_OK; | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| bzip->max_total_in = value; | ||
| return MZ_OK; | ||
| } | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
|
|
||
| void *mz_stream_bzip_create(void **stream) { | ||
| mz_stream_bzip *bzip = NULL; | ||
|
|
||
| bzip = (mz_stream_bzip *)MZ_ALLOC(sizeof(mz_stream_bzip)); | ||
| if (bzip != NULL) { | ||
| memset(bzip, 0, sizeof(mz_stream_bzip)); | ||
| bzip->stream.vtbl = &mz_stream_bzip_vtbl; | ||
| bzip->level = 6; | ||
| } | ||
| if (stream != NULL) | ||
| *stream = bzip; | ||
|
|
||
| return bzip; | ||
| } | ||
|
|
||
| void mz_stream_bzip_delete(void **stream) { | ||
| mz_stream_bzip *bzip = NULL; | ||
| if (stream == NULL) | ||
| return; | ||
| bzip = (mz_stream_bzip *)*stream; | ||
| if (bzip != NULL) | ||
| MZ_FREE(bzip); | ||
| *stream = NULL; | ||
| } | ||
|
|
||
| void *mz_stream_bzip_get_interface(void) { | ||
| return (void *)&mz_stream_bzip_vtbl; | ||
| } | ||
|
|
||
| extern void bz_internal_error(int errcode) { | ||
| MZ_UNUSED(errcode); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| /* mz_strm_bzip.h -- Stream for bzip inflate/deflate | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
| #ifndef MZ_STREAM_BZIP_H | ||
| #define MZ_STREAM_BZIP_H | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_bzip_open(void *stream, const char *filename, int32_t mode); | ||
| int32_t mz_stream_bzip_is_open(void *stream); | ||
| int32_t mz_stream_bzip_read(void *stream, void *buf, int32_t size); | ||
| int32_t mz_stream_bzip_write(void *stream, const void *buf, int32_t size); | ||
| int64_t mz_stream_bzip_tell(void *stream); | ||
| int32_t mz_stream_bzip_seek(void *stream, int64_t offset, int32_t origin); | ||
| int32_t mz_stream_bzip_close(void *stream); | ||
| int32_t mz_stream_bzip_error(void *stream); | ||
|
|
||
| int32_t mz_stream_bzip_get_prop_int64(void *stream, int32_t prop, int64_t *value); | ||
| int32_t mz_stream_bzip_set_prop_int64(void *stream, int32_t prop, int64_t value); | ||
|
|
||
| void* mz_stream_bzip_create(void **stream); | ||
| void mz_stream_bzip_delete(void **stream); | ||
|
|
||
| void* mz_stream_bzip_get_interface(void); | ||
|
|
||
| void bz_internal_error(int errcode); | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,356 @@ | ||
| /* mz_strm_libcomp.c -- Stream for apple compression | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
|
|
||
| #include "mz.h" | ||
| #include "mz_strm.h" | ||
| #include "mz_strm_libcomp.h" | ||
|
|
||
| #include <compression.h> | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static mz_stream_vtbl mz_stream_libcomp_vtbl = { | ||
| mz_stream_libcomp_open, | ||
| mz_stream_libcomp_is_open, | ||
| mz_stream_libcomp_read, | ||
| mz_stream_libcomp_write, | ||
| mz_stream_libcomp_tell, | ||
| mz_stream_libcomp_seek, | ||
| mz_stream_libcomp_close, | ||
| mz_stream_libcomp_error, | ||
| mz_stream_libcomp_create, | ||
| mz_stream_libcomp_delete, | ||
| mz_stream_libcomp_get_prop_int64, | ||
| mz_stream_libcomp_set_prop_int64 | ||
| }; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| typedef struct mz_stream_libcomp_s { | ||
| mz_stream stream; | ||
| compression_stream | ||
| cstream; | ||
| uint8_t buffer[INT16_MAX]; | ||
| int32_t buffer_len; | ||
| int64_t total_in; | ||
| int64_t total_out; | ||
| int64_t max_total_in; | ||
| int8_t initialized; | ||
| int32_t mode; | ||
| int32_t error; | ||
| int16_t method; | ||
| } mz_stream_libcomp; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_libcomp_open(void *stream, const char *path, int32_t mode) { | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
| int32_t err = 0; | ||
| int16_t operation = 0; | ||
| compression_algorithm algorithm = 0; | ||
|
|
||
| MZ_UNUSED(path); | ||
|
|
||
| if (libcomp->method == 0) | ||
| return MZ_PARAM_ERROR; | ||
|
|
||
| libcomp->total_in = 0; | ||
| libcomp->total_out = 0; | ||
|
|
||
| if (mode & MZ_OPEN_MODE_WRITE) { | ||
| #ifdef MZ_ZIP_NO_COMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| operation = COMPRESSION_STREAM_ENCODE; | ||
| #endif | ||
| } else if (mode & MZ_OPEN_MODE_READ) { | ||
| #ifdef MZ_ZIP_NO_DECOMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| operation = COMPRESSION_STREAM_DECODE; | ||
| #endif | ||
| } | ||
|
|
||
| if (libcomp->method == MZ_COMPRESS_METHOD_DEFLATE) | ||
| algorithm = COMPRESSION_ZLIB; | ||
| else if (libcomp->method == MZ_COMPRESS_METHOD_XZ) | ||
| algorithm = COMPRESSION_LZMA; | ||
| else | ||
| return MZ_SUPPORT_ERROR; | ||
|
|
||
| err = compression_stream_init(&libcomp->cstream, (compression_stream_operation)operation, algorithm); | ||
|
|
||
| if (err == COMPRESSION_STATUS_ERROR) { | ||
| libcomp->error = err; | ||
| return MZ_OPEN_ERROR; | ||
| } | ||
|
|
||
| libcomp->initialized = 1; | ||
| libcomp->mode = mode; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_libcomp_is_open(void *stream) { | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
| if (libcomp->initialized != 1) | ||
| return MZ_OPEN_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_libcomp_read(void *stream, void *buf, int32_t size) { | ||
| #ifdef MZ_ZIP_NO_DECOMPRESSION | ||
| MZ_UNUSED(stream); | ||
| MZ_UNUSED(buf); | ||
| MZ_UNUSED(size); | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
| uint64_t total_in_before = 0; | ||
| uint64_t total_in_after = 0; | ||
| uint64_t total_out_before = 0; | ||
| uint64_t total_out_after = 0; | ||
| int32_t total_in = 0; | ||
| int32_t total_out = 0; | ||
| int32_t in_bytes = 0; | ||
| int32_t out_bytes = 0; | ||
| int32_t bytes_to_read = sizeof(libcomp->buffer); | ||
| int32_t read = 0; | ||
| int32_t err = MZ_OK; | ||
| int16_t flags = 0; | ||
|
|
||
| libcomp->cstream.dst_ptr = buf; | ||
| libcomp->cstream.dst_size = (size_t)size; | ||
|
|
||
| do { | ||
| if (libcomp->cstream.src_size == 0) { | ||
| if (libcomp->max_total_in > 0) { | ||
| if ((int64_t)bytes_to_read > (libcomp->max_total_in - libcomp->total_in)) | ||
| bytes_to_read = (int32_t)(libcomp->max_total_in - libcomp->total_in); | ||
| } | ||
|
|
||
| read = mz_stream_read(libcomp->stream.base, libcomp->buffer, bytes_to_read); | ||
|
|
||
| if (read < 0) | ||
| return read; | ||
| if (read == 0) | ||
| flags = COMPRESSION_STREAM_FINALIZE; | ||
|
|
||
| libcomp->cstream.src_ptr = libcomp->buffer; | ||
| libcomp->cstream.src_size = (size_t)read; | ||
| } | ||
|
|
||
| total_in_before = libcomp->cstream.src_size; | ||
| total_out_before = libcomp->cstream.dst_size; | ||
|
|
||
| err = compression_stream_process(&libcomp->cstream, flags); | ||
| if (err == COMPRESSION_STATUS_ERROR) { | ||
| libcomp->error = err; | ||
| break; | ||
| } | ||
|
|
||
| total_in_after = libcomp->cstream.src_size; | ||
| total_out_after = libcomp->cstream.dst_size; | ||
|
|
||
| in_bytes = (int32_t)(total_in_before - total_in_after); | ||
| out_bytes = (int32_t)(total_out_before - total_out_after); | ||
|
|
||
| total_in += in_bytes; | ||
| total_out += out_bytes; | ||
|
|
||
| libcomp->total_in += in_bytes; | ||
| libcomp->total_out += out_bytes; | ||
|
|
||
| if (err == COMPRESSION_STATUS_END) | ||
| break; | ||
| if (err != COMPRESSION_STATUS_OK) { | ||
| libcomp->error = err; | ||
| break; | ||
| } | ||
| } while (libcomp->cstream.dst_size > 0); | ||
|
|
||
| if (libcomp->error != 0) | ||
| return MZ_DATA_ERROR; | ||
|
|
||
| return total_out; | ||
| #endif | ||
| } | ||
|
|
||
| static int32_t mz_stream_libcomp_flush(void *stream) { | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
| if (mz_stream_write(libcomp->stream.base, libcomp->buffer, libcomp->buffer_len) != libcomp->buffer_len) | ||
| return MZ_WRITE_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| static int32_t mz_stream_libcomp_deflate(void *stream, int flush) { | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
| uint64_t total_out_before = 0; | ||
| uint64_t total_out_after = 0; | ||
| uint32_t out_bytes = 0; | ||
| int32_t err = MZ_OK; | ||
|
|
||
|
|
||
| do { | ||
| if (libcomp->cstream.dst_size == 0) { | ||
| err = mz_stream_libcomp_flush(libcomp); | ||
| if (err != MZ_OK) { | ||
| libcomp->error = err; | ||
| return err; | ||
| } | ||
|
|
||
| libcomp->cstream.dst_size = sizeof(libcomp->buffer); | ||
| libcomp->cstream.dst_ptr = libcomp->buffer; | ||
|
|
||
| libcomp->buffer_len = 0; | ||
| } | ||
|
|
||
| total_out_before = libcomp->cstream.dst_size; | ||
| err = compression_stream_process(&libcomp->cstream, flush); | ||
| total_out_after = libcomp->cstream.dst_size; | ||
|
|
||
| out_bytes = (uint32_t)(total_out_before - total_out_after); | ||
|
|
||
| libcomp->buffer_len += out_bytes; | ||
| libcomp->total_out += out_bytes; | ||
|
|
||
| if (err == COMPRESSION_STATUS_END) | ||
| break; | ||
| if (err != COMPRESSION_STATUS_OK) { | ||
| libcomp->error = err; | ||
| return MZ_DATA_ERROR; | ||
| } | ||
| } while ((libcomp->cstream.src_size > 0) || (flush == COMPRESSION_STREAM_FINALIZE && err == COMPRESSION_STATUS_OK)); | ||
|
|
||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_libcomp_write(void *stream, const void *buf, int32_t size) { | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
| int32_t err = size; | ||
|
|
||
| #ifdef MZ_ZIP_NO_COMPRESSION | ||
| MZ_UNUSED(libcomp); | ||
| err = MZ_SUPPORT_ERROR; | ||
| #else | ||
| libcomp->cstream.src_ptr = buf; | ||
| libcomp->cstream.src_size = (size_t)size; | ||
|
|
||
| mz_stream_libcomp_deflate(stream, 0); | ||
|
|
||
| libcomp->total_in += size; | ||
| #endif | ||
| return err; | ||
| } | ||
|
|
||
| int64_t mz_stream_libcomp_tell(void *stream) { | ||
| MZ_UNUSED(stream); | ||
|
|
||
| return MZ_TELL_ERROR; | ||
| } | ||
|
|
||
| int32_t mz_stream_libcomp_seek(void *stream, int64_t offset, int32_t origin) { | ||
| MZ_UNUSED(stream); | ||
| MZ_UNUSED(offset); | ||
| MZ_UNUSED(origin); | ||
|
|
||
| return MZ_SEEK_ERROR; | ||
| } | ||
|
|
||
| int32_t mz_stream_libcomp_close(void *stream) { | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
|
|
||
|
|
||
| if (libcomp->mode & MZ_OPEN_MODE_WRITE) { | ||
| #ifdef MZ_ZIP_NO_COMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| mz_stream_libcomp_deflate(stream, COMPRESSION_STREAM_FINALIZE); | ||
| mz_stream_libcomp_flush(stream); | ||
| #endif | ||
| } else if (libcomp->mode & MZ_OPEN_MODE_READ) { | ||
| #ifdef MZ_ZIP_NO_DECOMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #endif | ||
| } | ||
|
|
||
| compression_stream_destroy(&libcomp->cstream); | ||
|
|
||
| libcomp->initialized = 0; | ||
|
|
||
| if (libcomp->error != MZ_OK) | ||
| return MZ_CLOSE_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_libcomp_error(void *stream) { | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
| return libcomp->error; | ||
| } | ||
|
|
||
| int32_t mz_stream_libcomp_get_prop_int64(void *stream, int32_t prop, int64_t *value) { | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_TOTAL_IN: | ||
| *value = libcomp->total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| *value = libcomp->max_total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_OUT: | ||
| *value = libcomp->total_out; | ||
| break; | ||
| case MZ_STREAM_PROP_HEADER_SIZE: | ||
| *value = 0; | ||
| break; | ||
| default: | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_libcomp_set_prop_int64(void *stream, int32_t prop, int64_t value) { | ||
| mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_COMPRESS_METHOD: | ||
| libcomp->method = (int16_t)value; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| libcomp->max_total_in = value; | ||
| break; | ||
| default: | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| void *mz_stream_libcomp_create(void **stream) { | ||
| mz_stream_libcomp *libcomp = NULL; | ||
|
|
||
| libcomp = (mz_stream_libcomp *)MZ_ALLOC(sizeof(mz_stream_libcomp)); | ||
| if (libcomp != NULL) { | ||
| memset(libcomp, 0, sizeof(mz_stream_libcomp)); | ||
| libcomp->stream.vtbl = &mz_stream_libcomp_vtbl; | ||
| } | ||
| if (stream != NULL) | ||
| *stream = libcomp; | ||
|
|
||
| return libcomp; | ||
| } | ||
|
|
||
| void mz_stream_libcomp_delete(void **stream) { | ||
| mz_stream_libcomp *libcomp = NULL; | ||
| if (stream == NULL) | ||
| return; | ||
| libcomp = (mz_stream_libcomp *)*stream; | ||
| if (libcomp != NULL) | ||
| MZ_FREE(libcomp); | ||
| *stream = NULL; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| /* mz_strm_libcomp.h -- Stream for apple compression | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
| #ifndef MZ_STREAM_LIBCOMP_H | ||
| #define MZ_STREAM_LIBCOMP_H | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_libcomp_open(void *stream, const char *filename, int32_t mode); | ||
| int32_t mz_stream_libcomp_is_open(void *stream); | ||
| int32_t mz_stream_libcomp_read(void *stream, void *buf, int32_t size); | ||
| int32_t mz_stream_libcomp_write(void *stream, const void *buf, int32_t size); | ||
| int64_t mz_stream_libcomp_tell(void *stream); | ||
| int32_t mz_stream_libcomp_seek(void *stream, int64_t offset, int32_t origin); | ||
| int32_t mz_stream_libcomp_close(void *stream); | ||
| int32_t mz_stream_libcomp_error(void *stream); | ||
|
|
||
| int32_t mz_stream_libcomp_get_prop_int64(void *stream, int32_t prop, int64_t *value); | ||
| int32_t mz_stream_libcomp_set_prop_int64(void *stream, int32_t prop, int64_t value); | ||
|
|
||
| void* mz_stream_libcomp_create(void **stream); | ||
| void mz_stream_libcomp_delete(void **stream); | ||
|
|
||
| void* mz_stream_libcomp_get_interface(void); | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* mz_strm_lzma.h -- Stream for lzma inflate/deflate | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as lzma. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
| #ifndef MZ_STREAM_LZMA_H | ||
| #define MZ_STREAM_LZMA_H | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_lzma_open(void *stream, const char *filename, int32_t mode); | ||
| int32_t mz_stream_lzma_is_open(void *stream); | ||
| int32_t mz_stream_lzma_read(void *stream, void *buf, int32_t size); | ||
| int32_t mz_stream_lzma_write(void *stream, const void *buf, int32_t size); | ||
| int64_t mz_stream_lzma_tell(void *stream); | ||
| int32_t mz_stream_lzma_seek(void *stream, int64_t offset, int32_t origin); | ||
| int32_t mz_stream_lzma_close(void *stream); | ||
| int32_t mz_stream_lzma_error(void *stream); | ||
|
|
||
| int32_t mz_stream_lzma_get_prop_int64(void *stream, int32_t prop, int64_t *value); | ||
| int32_t mz_stream_lzma_set_prop_int64(void *stream, int32_t prop, int64_t value); | ||
|
|
||
| void* mz_stream_lzma_create(void **stream); | ||
| void mz_stream_lzma_delete(void **stream); | ||
|
|
||
| void* mz_stream_lzma_get_interface(void); | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,272 @@ | ||
| /* mz_strm_mem.c -- Stream for memory access | ||
| part of the minizip-ng project | ||
| This interface is designed to access memory rather than files. | ||
| We do use a region of memory to put data in to and take it out of. | ||
| Based on Unzip ioapi.c version 0.22, May 19th, 2003 | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| Copyright (C) 2003 Justin Fletcher | ||
| Copyright (C) 1998-2003 Gilles Vollant | ||
| https://www.winimage.com/zLibDll/minizip.html | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
|
|
||
| #include "mz.h" | ||
| #include "mz_strm.h" | ||
| #include "mz_strm_mem.h" | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static mz_stream_vtbl mz_stream_mem_vtbl = { | ||
| mz_stream_mem_open, | ||
| mz_stream_mem_is_open, | ||
| mz_stream_mem_read, | ||
| mz_stream_mem_write, | ||
| mz_stream_mem_tell, | ||
| mz_stream_mem_seek, | ||
| mz_stream_mem_close, | ||
| mz_stream_mem_error, | ||
| mz_stream_mem_create, | ||
| mz_stream_mem_delete, | ||
| NULL, | ||
| NULL | ||
| }; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| typedef struct mz_stream_mem_s { | ||
| mz_stream stream; | ||
| int32_t mode; | ||
| uint8_t *buffer; /* Memory buffer pointer */ | ||
| int32_t size; /* Size of the memory buffer */ | ||
| int32_t limit; /* Furthest we've written */ | ||
| int32_t position; /* Current position in the memory */ | ||
| int32_t grow_size; /* Size to grow when full */ | ||
| } mz_stream_mem; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static int32_t mz_stream_mem_set_size(void *stream, int32_t size) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| int32_t new_size = size; | ||
| uint8_t *new_buf = NULL; | ||
|
|
||
|
|
||
| new_buf = (uint8_t *)MZ_ALLOC((uint32_t)new_size); | ||
| if (new_buf == NULL) | ||
| return MZ_BUF_ERROR; | ||
|
|
||
| if (mem->buffer) { | ||
| memcpy(new_buf, mem->buffer, mem->size); | ||
| MZ_FREE(mem->buffer); | ||
| } | ||
|
|
||
| mem->buffer = new_buf; | ||
| mem->size = new_size; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_open(void *stream, const char *path, int32_t mode) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| int32_t err = MZ_OK; | ||
|
|
||
| MZ_UNUSED(path); | ||
|
|
||
| mem->mode = mode; | ||
| mem->limit = 0; | ||
| mem->position = 0; | ||
|
|
||
| if (mem->mode & MZ_OPEN_MODE_CREATE) | ||
| err = mz_stream_mem_set_size(stream, mem->grow_size); | ||
| else | ||
| mem->limit = mem->size; | ||
|
|
||
| return err; | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_is_open(void *stream) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| if (mem->buffer == NULL) | ||
| return MZ_OPEN_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
|
|
||
| if (size > mem->size - mem->position) | ||
| size = mem->size - mem->position; | ||
| if (mem->position + size > mem->limit) | ||
| size = mem->limit - mem->position; | ||
|
|
||
| if (size <= 0) | ||
| return 0; | ||
|
|
||
| memcpy(buf, mem->buffer + mem->position, size); | ||
| mem->position += size; | ||
|
|
||
| return size; | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| int32_t new_size = 0; | ||
| int32_t err = MZ_OK; | ||
|
|
||
| if (size == 0) | ||
| return size; | ||
|
|
||
| if (size > mem->size - mem->position) { | ||
| if (mem->mode & MZ_OPEN_MODE_CREATE) { | ||
| new_size = mem->size; | ||
| if (size < mem->grow_size) | ||
| new_size += mem->grow_size; | ||
| else | ||
| new_size += size; | ||
|
|
||
| err = mz_stream_mem_set_size(stream, new_size); | ||
| if (err != MZ_OK) | ||
| return err; | ||
| } else { | ||
| size = mem->size - mem->position; | ||
| } | ||
| } | ||
|
|
||
| memcpy(mem->buffer + mem->position, buf, size); | ||
|
|
||
| mem->position += size; | ||
| if (mem->position > mem->limit) | ||
| mem->limit = mem->position; | ||
|
|
||
| return size; | ||
| } | ||
|
|
||
| int64_t mz_stream_mem_tell(void *stream) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| return mem->position; | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| int64_t new_pos = 0; | ||
| int32_t err = MZ_OK; | ||
|
|
||
| switch (origin) { | ||
| case MZ_SEEK_CUR: | ||
| new_pos = mem->position + offset; | ||
| break; | ||
| case MZ_SEEK_END: | ||
| new_pos = mem->limit + offset; | ||
| break; | ||
| case MZ_SEEK_SET: | ||
| new_pos = offset; | ||
| break; | ||
| default: | ||
| return MZ_SEEK_ERROR; | ||
| } | ||
|
|
||
| if (new_pos > mem->size) { | ||
| if ((mem->mode & MZ_OPEN_MODE_CREATE) == 0) | ||
| return MZ_SEEK_ERROR; | ||
|
|
||
| err = mz_stream_mem_set_size(stream, (int32_t)new_pos); | ||
| if (err != MZ_OK) | ||
| return err; | ||
| } else if (new_pos < 0) { | ||
| return MZ_SEEK_ERROR; | ||
| } | ||
|
|
||
| mem->position = (int32_t)new_pos; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_close(void *stream) { | ||
| MZ_UNUSED(stream); | ||
|
|
||
| /* We never return errors */ | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_error(void *stream) { | ||
| MZ_UNUSED(stream); | ||
|
|
||
| /* We never return errors */ | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| mem->buffer = (uint8_t *)buf; | ||
| mem->size = size; | ||
| mem->limit = size; | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_get_buffer(void *stream, const void **buf) { | ||
| return mz_stream_mem_get_buffer_at(stream, 0, buf); | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| if (buf == NULL || position < 0 || mem->size < position || mem->buffer == NULL) | ||
| return MZ_SEEK_ERROR; | ||
| *buf = mem->buffer + position; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| return mz_stream_mem_get_buffer_at(stream, mem->position, buf); | ||
| } | ||
|
|
||
| void mz_stream_mem_get_buffer_length(void *stream, int32_t *length) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| *length = mem->limit; | ||
| } | ||
|
|
||
| void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| mem->limit = limit; | ||
| } | ||
|
|
||
| void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size) { | ||
| mz_stream_mem *mem = (mz_stream_mem *)stream; | ||
| mem->grow_size = grow_size; | ||
| } | ||
|
|
||
| void *mz_stream_mem_create(void **stream) { | ||
| mz_stream_mem *mem = NULL; | ||
|
|
||
| mem = (mz_stream_mem *)MZ_ALLOC(sizeof(mz_stream_mem)); | ||
| if (mem != NULL) { | ||
| memset(mem, 0, sizeof(mz_stream_mem)); | ||
| mem->stream.vtbl = &mz_stream_mem_vtbl; | ||
| mem->grow_size = 4096; | ||
| } | ||
| if (stream != NULL) | ||
| *stream = mem; | ||
|
|
||
| return mem; | ||
| } | ||
|
|
||
| void mz_stream_mem_delete(void **stream) { | ||
| mz_stream_mem *mem = NULL; | ||
| if (stream == NULL) | ||
| return; | ||
| mem = (mz_stream_mem *)*stream; | ||
| if (mem != NULL) { | ||
| if ((mem->mode & MZ_OPEN_MODE_CREATE) && (mem->buffer != NULL)) | ||
| MZ_FREE(mem->buffer); | ||
| MZ_FREE(mem); | ||
| } | ||
| *stream = NULL; | ||
| } | ||
|
|
||
| void *mz_stream_mem_get_interface(void) { | ||
| return (void *)&mz_stream_mem_vtbl; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| /* mz_strm_mem.h -- Stream for memory access | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
| #ifndef MZ_STREAM_MEM_H | ||
| #define MZ_STREAM_MEM_H | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_mem_open(void *stream, const char *filename, int32_t mode); | ||
| int32_t mz_stream_mem_is_open(void *stream); | ||
| int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size); | ||
| int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size); | ||
| int64_t mz_stream_mem_tell(void *stream); | ||
| int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin); | ||
| int32_t mz_stream_mem_close(void *stream); | ||
| int32_t mz_stream_mem_error(void *stream); | ||
|
|
||
| void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size); | ||
| int32_t mz_stream_mem_get_buffer(void *stream, const void **buf); | ||
| int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf); | ||
| int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf); | ||
| void mz_stream_mem_get_buffer_length(void *stream, int32_t *length); | ||
| void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit); | ||
| void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size); | ||
|
|
||
| void* mz_stream_mem_create(void **stream); | ||
| void mz_stream_mem_delete(void **stream); | ||
|
|
||
| void* mz_stream_mem_get_interface(void); | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /* mz_sstrm_os.h -- Stream for filesystem access | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
| #ifndef MZ_STREAM_OS_H | ||
| #define MZ_STREAM_OS_H | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode); | ||
| int32_t mz_stream_os_is_open(void *stream); | ||
| int32_t mz_stream_os_read(void *stream, void *buf, int32_t size); | ||
| int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size); | ||
| int64_t mz_stream_os_tell(void *stream); | ||
| int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin); | ||
| int32_t mz_stream_os_close(void *stream); | ||
| int32_t mz_stream_os_error(void *stream); | ||
|
|
||
| void* mz_stream_os_create(void **stream); | ||
| void mz_stream_os_delete(void **stream); | ||
|
|
||
| void* mz_stream_os_get_interface(void); | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,206 @@ | ||
| /* mz_strm_posix.c -- Stream for filesystem access for posix/linux | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| Modifications for Zip64 support | ||
| Copyright (C) 2009-2010 Mathias Svensson | ||
| http://result42.com | ||
| Copyright (C) 1998-2010 Gilles Vollant | ||
| https://www.winimage.com/zLibDll/minizip.html | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
|
|
||
| #include "mz.h" | ||
| #include "mz_strm.h" | ||
| #include "mz_strm_os.h" | ||
|
|
||
| #include <stdio.h> /* fopen, fread.. */ | ||
| #include <errno.h> | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #define fopen64 fopen | ||
| #ifndef MZ_FILE32_API | ||
| # ifndef NO_FSEEKO | ||
| # define ftello64 ftello | ||
| # define fseeko64 fseeko | ||
| # elif defined(_MSC_VER) && (_MSC_VER >= 1400) | ||
| # define ftello64 _ftelli64 | ||
| # define fseeko64 _fseeki64 | ||
| # endif | ||
| #endif | ||
| #ifndef ftello64 | ||
| # define ftello64 ftell | ||
| #endif | ||
| #ifndef fseeko64 | ||
| # define fseeko64 fseek | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static mz_stream_vtbl mz_stream_os_vtbl = { | ||
| mz_stream_os_open, | ||
| mz_stream_os_is_open, | ||
| mz_stream_os_read, | ||
| mz_stream_os_write, | ||
| mz_stream_os_tell, | ||
| mz_stream_os_seek, | ||
| mz_stream_os_close, | ||
| mz_stream_os_error, | ||
| mz_stream_os_create, | ||
| mz_stream_os_delete, | ||
| NULL, | ||
| NULL | ||
| }; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| typedef struct mz_stream_posix_s { | ||
| mz_stream stream; | ||
| int32_t error; | ||
| FILE *handle; | ||
| } mz_stream_posix; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) { | ||
| mz_stream_posix *posix = (mz_stream_posix *)stream; | ||
| const char *mode_fopen = NULL; | ||
|
|
||
| if (path == NULL) | ||
| return MZ_PARAM_ERROR; | ||
|
|
||
| if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) | ||
| mode_fopen = "rb"; | ||
| else if (mode & MZ_OPEN_MODE_APPEND) | ||
| mode_fopen = "r+b"; | ||
| else if (mode & MZ_OPEN_MODE_CREATE) | ||
| mode_fopen = "wb"; | ||
| else | ||
| return MZ_OPEN_ERROR; | ||
|
|
||
| posix->handle = fopen64(path, mode_fopen); | ||
| if (posix->handle == NULL) { | ||
| posix->error = errno; | ||
| return MZ_OPEN_ERROR; | ||
| } | ||
|
|
||
| if (mode & MZ_OPEN_MODE_APPEND) | ||
| return mz_stream_os_seek(stream, 0, MZ_SEEK_END); | ||
|
|
||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_is_open(void *stream) { | ||
| mz_stream_posix *posix = (mz_stream_posix*)stream; | ||
| if (posix->handle == NULL) | ||
| return MZ_OPEN_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) { | ||
| mz_stream_posix *posix = (mz_stream_posix*)stream; | ||
| int32_t read = (int32_t)fread(buf, 1, (size_t)size, posix->handle); | ||
| if (read < size && ferror(posix->handle)) { | ||
| posix->error = errno; | ||
| return MZ_READ_ERROR; | ||
| } | ||
| return read; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) { | ||
| mz_stream_posix *posix = (mz_stream_posix*)stream; | ||
| int32_t written = (int32_t)fwrite(buf, 1, (size_t)size, posix->handle); | ||
| if (written < size && ferror(posix->handle)) { | ||
| posix->error = errno; | ||
| return MZ_WRITE_ERROR; | ||
| } | ||
| return written; | ||
| } | ||
|
|
||
| int64_t mz_stream_os_tell(void *stream) { | ||
| mz_stream_posix *posix = (mz_stream_posix*)stream; | ||
| int64_t position = ftello64(posix->handle); | ||
| if (position == -1) { | ||
| posix->error = errno; | ||
| return MZ_TELL_ERROR; | ||
| } | ||
| return position; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) { | ||
| mz_stream_posix *posix = (mz_stream_posix*)stream; | ||
| int32_t fseek_origin = 0; | ||
|
|
||
| switch (origin) { | ||
| case MZ_SEEK_CUR: | ||
| fseek_origin = SEEK_CUR; | ||
| break; | ||
| case MZ_SEEK_END: | ||
| fseek_origin = SEEK_END; | ||
| break; | ||
| case MZ_SEEK_SET: | ||
| fseek_origin = SEEK_SET; | ||
| break; | ||
| default: | ||
| return MZ_SEEK_ERROR; | ||
| } | ||
|
|
||
| if (fseeko64(posix->handle, offset, fseek_origin) != 0) { | ||
| posix->error = errno; | ||
| return MZ_SEEK_ERROR; | ||
| } | ||
|
|
||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_close(void *stream) { | ||
| mz_stream_posix *posix = (mz_stream_posix*)stream; | ||
| int32_t closed = 0; | ||
| if (posix->handle != NULL) { | ||
| closed = fclose(posix->handle); | ||
| posix->handle = NULL; | ||
| } | ||
| if (closed != 0) { | ||
| posix->error = errno; | ||
| return MZ_CLOSE_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_error(void *stream) { | ||
| mz_stream_posix *posix = (mz_stream_posix*)stream; | ||
| return posix->error; | ||
| } | ||
|
|
||
| void *mz_stream_os_create(void **stream) { | ||
| mz_stream_posix *posix = NULL; | ||
|
|
||
| posix = (mz_stream_posix *)MZ_ALLOC(sizeof(mz_stream_posix)); | ||
| if (posix != NULL) { | ||
| memset(posix, 0, sizeof(mz_stream_posix)); | ||
| posix->stream.vtbl = &mz_stream_os_vtbl; | ||
| } | ||
| if (stream != NULL) | ||
| *stream = posix; | ||
|
|
||
| return posix; | ||
| } | ||
|
|
||
| void mz_stream_os_delete(void **stream) { | ||
| mz_stream_posix *posix = NULL; | ||
| if (stream == NULL) | ||
| return; | ||
| posix = (mz_stream_posix *)*stream; | ||
| if (posix != NULL) | ||
| MZ_FREE(posix); | ||
| *stream = NULL; | ||
| } | ||
|
|
||
| void *mz_stream_os_get_interface(void) { | ||
| return (void *)&mz_stream_os_vtbl; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,296 @@ | ||
| /* mz_strm_win32.c -- Stream for filesystem access for windows | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| Copyright (C) 2009-2010 Mathias Svensson | ||
| Modifications for Zip64 support | ||
| http://result42.com | ||
| Copyright (C) 1998-2010 Gilles Vollant | ||
| https://www.winimage.com/zLibDll/minizip.html | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
|
|
||
| #include "mz.h" | ||
| #include "mz_os.h" | ||
| #include "mz_strm.h" | ||
| #include "mz_strm_os.h" | ||
|
|
||
| #include <windows.h> | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #ifndef INVALID_HANDLE_VALUE | ||
| # define INVALID_HANDLE_VALUE (0xFFFFFFFF) | ||
| #endif | ||
|
|
||
| #ifndef INVALID_SET_FILE_POINTER | ||
| # define INVALID_SET_FILE_POINTER ((DWORD)-1) | ||
| #endif | ||
|
|
||
| #if defined(WINAPI_FAMILY_ONE_PARTITION) && !defined(MZ_WINRT_API) | ||
| # if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP) | ||
| # define MZ_WINRT_API 1 | ||
| # endif | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static mz_stream_vtbl mz_stream_os_vtbl = { | ||
| mz_stream_os_open, | ||
| mz_stream_os_is_open, | ||
| mz_stream_os_read, | ||
| mz_stream_os_write, | ||
| mz_stream_os_tell, | ||
| mz_stream_os_seek, | ||
| mz_stream_os_close, | ||
| mz_stream_os_error, | ||
| mz_stream_os_create, | ||
| mz_stream_os_delete, | ||
| NULL, | ||
| NULL | ||
| }; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| typedef struct mz_stream_win32_s { | ||
| mz_stream stream; | ||
| HANDLE handle; | ||
| int32_t error; | ||
| } mz_stream_win32; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #if 0 | ||
| # define mz_stream_os_print printf | ||
| #else | ||
| # define mz_stream_os_print(fmt,...) | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) { | ||
| mz_stream_win32 *win32 = (mz_stream_win32 *)stream; | ||
| uint32_t desired_access = 0; | ||
| uint32_t creation_disposition = 0; | ||
| uint32_t share_mode = FILE_SHARE_READ; | ||
| uint32_t flags_attribs = FILE_ATTRIBUTE_NORMAL; | ||
| wchar_t *path_wide = NULL; | ||
|
|
||
|
|
||
| if (path == NULL) | ||
| return MZ_PARAM_ERROR; | ||
|
|
||
| /* Some use cases require write sharing as well */ | ||
| share_mode |= FILE_SHARE_WRITE; | ||
|
|
||
| if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) { | ||
| desired_access = GENERIC_READ; | ||
| creation_disposition = OPEN_EXISTING; | ||
| } else if (mode & MZ_OPEN_MODE_APPEND) { | ||
| desired_access = GENERIC_WRITE | GENERIC_READ; | ||
| creation_disposition = OPEN_EXISTING; | ||
| } else if (mode & MZ_OPEN_MODE_CREATE) { | ||
| desired_access = GENERIC_WRITE | GENERIC_READ; | ||
| creation_disposition = CREATE_ALWAYS; | ||
| } else { | ||
| return MZ_PARAM_ERROR; | ||
| } | ||
|
|
||
| mz_stream_os_print("Win32 - Open - %s (mode %" PRId32 ")\n", path); | ||
|
|
||
| path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); | ||
| if (path_wide == NULL) | ||
| return MZ_PARAM_ERROR; | ||
|
|
||
| #ifdef MZ_WINRT_API | ||
| win32->handle = CreateFile2(path_wide, desired_access, share_mode, | ||
| creation_disposition, NULL); | ||
| #else | ||
| win32->handle = CreateFileW(path_wide, desired_access, share_mode, NULL, | ||
| creation_disposition, flags_attribs, NULL); | ||
| #endif | ||
|
|
||
| mz_os_unicode_string_delete(&path_wide); | ||
|
|
||
| if (mz_stream_os_is_open(stream) != MZ_OK) { | ||
| win32->error = GetLastError(); | ||
| return MZ_OPEN_ERROR; | ||
| } | ||
|
|
||
| if (mode & MZ_OPEN_MODE_APPEND) | ||
| return mz_stream_os_seek(stream, 0, MZ_SEEK_END); | ||
|
|
||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_is_open(void *stream) { | ||
| mz_stream_win32 *win32 = (mz_stream_win32 *)stream; | ||
| if (win32->handle == NULL || win32->handle == INVALID_HANDLE_VALUE) | ||
| return MZ_OPEN_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) { | ||
| mz_stream_win32 *win32 = (mz_stream_win32 *)stream; | ||
| uint32_t read = 0; | ||
|
|
||
| if (mz_stream_os_is_open(stream) != MZ_OK) | ||
| return MZ_OPEN_ERROR; | ||
|
|
||
| if (!ReadFile(win32->handle, buf, size, (DWORD *)&read, NULL)) { | ||
| win32->error = GetLastError(); | ||
| if (win32->error == ERROR_HANDLE_EOF) | ||
| win32->error = 0; | ||
| } | ||
|
|
||
| mz_stream_os_print("Win32 - Read - %" PRId32 "\n", read); | ||
|
|
||
| return read; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) { | ||
| mz_stream_win32 *win32 = (mz_stream_win32 *)stream; | ||
| int32_t written = 0; | ||
|
|
||
| if (mz_stream_os_is_open(stream) != MZ_OK) | ||
| return MZ_OPEN_ERROR; | ||
|
|
||
| if (!WriteFile(win32->handle, buf, size, (DWORD *)&written, NULL)) { | ||
| win32->error = GetLastError(); | ||
| if (win32->error == ERROR_HANDLE_EOF) | ||
| win32->error = 0; | ||
| } | ||
|
|
||
| mz_stream_os_print("Win32 - Write - %" PRId32 "\n", written); | ||
|
|
||
| return written; | ||
| } | ||
|
|
||
| static int32_t mz_stream_os_seekinternal(HANDLE handle, LARGE_INTEGER large_pos, | ||
| LARGE_INTEGER *new_pos, uint32_t move_method) { | ||
| #ifdef MZ_WINRT_API | ||
| BOOL success = FALSE; | ||
| success = SetFilePointerEx(handle, large_pos, new_pos, move_method); | ||
| if ((success == FALSE) && (GetLastError() != NO_ERROR)) | ||
| return MZ_SEEK_ERROR; | ||
|
|
||
| return MZ_OK; | ||
| #else | ||
| LONG high_part = 0; | ||
| uint32_t pos = 0; | ||
|
|
||
| high_part = large_pos.HighPart; | ||
| pos = SetFilePointer(handle, large_pos.LowPart, &high_part, move_method); | ||
|
|
||
| if ((pos == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR)) | ||
| return MZ_SEEK_ERROR; | ||
|
|
||
| if (new_pos != NULL) { | ||
| new_pos->LowPart = pos; | ||
| new_pos->HighPart = high_part; | ||
| } | ||
|
|
||
| return MZ_OK; | ||
| #endif | ||
| } | ||
|
|
||
| int64_t mz_stream_os_tell(void *stream) { | ||
| mz_stream_win32 *win32 = (mz_stream_win32 *)stream; | ||
| LARGE_INTEGER large_pos; | ||
|
|
||
| if (mz_stream_os_is_open(stream) != MZ_OK) | ||
| return MZ_OPEN_ERROR; | ||
|
|
||
| large_pos.QuadPart = 0; | ||
|
|
||
| if (mz_stream_os_seekinternal(win32->handle, large_pos, &large_pos, FILE_CURRENT) != MZ_OK) | ||
| win32->error = GetLastError(); | ||
|
|
||
| mz_stream_os_print("Win32 - Tell - %" PRId64 "\n", large_pos.QuadPart); | ||
|
|
||
| return large_pos.QuadPart; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) { | ||
| mz_stream_win32 *win32 = (mz_stream_win32 *)stream; | ||
| uint32_t move_method = 0xFFFFFFFF; | ||
| int32_t err = MZ_OK; | ||
| LARGE_INTEGER large_pos; | ||
|
|
||
|
|
||
| if (mz_stream_os_is_open(stream) != MZ_OK) | ||
| return MZ_OPEN_ERROR; | ||
|
|
||
| switch (origin) { | ||
| case MZ_SEEK_CUR: | ||
| move_method = FILE_CURRENT; | ||
| break; | ||
| case MZ_SEEK_END: | ||
| move_method = FILE_END; | ||
| break; | ||
| case MZ_SEEK_SET: | ||
| move_method = FILE_BEGIN; | ||
| break; | ||
| default: | ||
| return MZ_SEEK_ERROR; | ||
| } | ||
|
|
||
| mz_stream_os_print("Win32 - Seek - %" PRId64 " (origin %" PRId32 ")\n", offset, origin); | ||
|
|
||
| large_pos.QuadPart = offset; | ||
|
|
||
| err = mz_stream_os_seekinternal(win32->handle, large_pos, NULL, move_method); | ||
| if (err != MZ_OK) { | ||
| win32->error = GetLastError(); | ||
| return err; | ||
| } | ||
|
|
||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_close(void *stream) { | ||
| mz_stream_win32 *win32 = (mz_stream_win32 *)stream; | ||
|
|
||
| if (win32->handle != NULL) | ||
| CloseHandle(win32->handle); | ||
| mz_stream_os_print("Win32 - Close\n"); | ||
| win32->handle = NULL; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_os_error(void *stream) { | ||
| mz_stream_win32 *win32 = (mz_stream_win32 *)stream; | ||
| return win32->error; | ||
| } | ||
|
|
||
| void *mz_stream_os_create(void **stream) { | ||
| mz_stream_win32 *win32 = NULL; | ||
|
|
||
| win32 = (mz_stream_win32 *)MZ_ALLOC(sizeof(mz_stream_win32)); | ||
| if (win32 != NULL) { | ||
| memset(win32, 0, sizeof(mz_stream_win32)); | ||
| win32->stream.vtbl = &mz_stream_os_vtbl; | ||
| } | ||
| if (stream != NULL) | ||
| *stream = win32; | ||
|
|
||
| return win32; | ||
| } | ||
|
|
||
| void mz_stream_os_delete(void **stream) { | ||
| mz_stream_win32 *win32 = NULL; | ||
| if (stream == NULL) | ||
| return; | ||
| win32 = (mz_stream_win32 *)*stream; | ||
| if (win32 != NULL) | ||
| MZ_FREE(win32); | ||
| *stream = NULL; | ||
| } | ||
|
|
||
| void *mz_stream_os_get_interface(void) { | ||
| return (void *)&mz_stream_os_vtbl; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,338 @@ | ||
| /* mz_strm_pkcrypt.c -- Code for traditional PKWARE encryption | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| Copyright (C) 1998-2005 Gilles Vollant | ||
| Modifications for Info-ZIP crypting | ||
| https://www.winimage.com/zLibDll/minizip.html | ||
| Copyright (C) 2003 Terry Thorsen | ||
| This code is a modified version of crypting code in Info-ZIP distribution | ||
| Copyright (C) 1990-2000 Info-ZIP. All rights reserved. | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| This encryption code is a direct transcription of the algorithm from | ||
| Roger Schlafly, described by Phil Katz in the file appnote.txt. This | ||
| file (appnote.txt) is distributed with the PKZIP program (even in the | ||
| version without encryption capabilities). | ||
| */ | ||
|
|
||
|
|
||
| #include "mz.h" | ||
| #include "mz_crypt.h" | ||
| #include "mz_strm.h" | ||
| #include "mz_strm_pkcrypt.h" | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static mz_stream_vtbl mz_stream_pkcrypt_vtbl = { | ||
| mz_stream_pkcrypt_open, | ||
| mz_stream_pkcrypt_is_open, | ||
| mz_stream_pkcrypt_read, | ||
| mz_stream_pkcrypt_write, | ||
| mz_stream_pkcrypt_tell, | ||
| mz_stream_pkcrypt_seek, | ||
| mz_stream_pkcrypt_close, | ||
| mz_stream_pkcrypt_error, | ||
| mz_stream_pkcrypt_create, | ||
| mz_stream_pkcrypt_delete, | ||
| mz_stream_pkcrypt_get_prop_int64, | ||
| mz_stream_pkcrypt_set_prop_int64 | ||
| }; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| typedef struct mz_stream_pkcrypt_s { | ||
| mz_stream stream; | ||
| int32_t error; | ||
| int16_t initialized; | ||
| uint8_t buffer[UINT16_MAX]; | ||
| int64_t total_in; | ||
| int64_t max_total_in; | ||
| int64_t total_out; | ||
| uint32_t keys[3]; /* keys defining the pseudo-random sequence */ | ||
| uint8_t verify1; | ||
| uint8_t verify2; | ||
| const char *password; | ||
| } mz_stream_pkcrypt; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #define mz_stream_pkcrypt_decode(strm, c) \ | ||
| (mz_stream_pkcrypt_update_keys(strm, \ | ||
| c ^= mz_stream_pkcrypt_decrypt_byte(strm))) | ||
|
|
||
| #define mz_stream_pkcrypt_encode(strm, c, t) \ | ||
| (t = mz_stream_pkcrypt_decrypt_byte(strm), \ | ||
| mz_stream_pkcrypt_update_keys(strm, (uint8_t)c), (uint8_t)(t^(c))) | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static uint8_t mz_stream_pkcrypt_decrypt_byte(void *stream) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
|
|
||
| unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an */ | ||
| /* unpredictable manner on 16-bit systems; not a problem */ | ||
| /* with any known compiler so far, though. */ | ||
|
|
||
| temp = pkcrypt->keys[2] | 2; | ||
| return (uint8_t)(((temp * (temp ^ 1)) >> 8) & 0xff); | ||
| } | ||
|
|
||
| static uint8_t mz_stream_pkcrypt_update_keys(void *stream, uint8_t c) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| uint8_t buf = c; | ||
|
|
||
| pkcrypt->keys[0] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[0], &buf, 1); | ||
|
|
||
| pkcrypt->keys[1] += pkcrypt->keys[0] & 0xff; | ||
| pkcrypt->keys[1] *= 134775813L; | ||
| pkcrypt->keys[1] += 1; | ||
|
|
||
| buf = (uint8_t)(pkcrypt->keys[1] >> 24); | ||
| pkcrypt->keys[2] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[2], &buf, 1); | ||
|
|
||
| return (uint8_t)c; | ||
| } | ||
|
|
||
| static void mz_stream_pkcrypt_init_keys(void *stream, const char *password) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
|
|
||
| pkcrypt->keys[0] = 305419896L; | ||
| pkcrypt->keys[1] = 591751049L; | ||
| pkcrypt->keys[2] = 878082192L; | ||
|
|
||
| while (*password != 0) { | ||
| mz_stream_pkcrypt_update_keys(stream, (uint8_t)*password); | ||
| password += 1; | ||
| } | ||
| } | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_pkcrypt_open(void *stream, const char *path, int32_t mode) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| uint16_t t = 0; | ||
| int16_t i = 0; | ||
| uint8_t verify1 = 0; | ||
| uint8_t verify2 = 0; | ||
| uint8_t header[MZ_PKCRYPT_HEADER_SIZE]; | ||
| const char *password = path; | ||
|
|
||
| pkcrypt->total_in = 0; | ||
| pkcrypt->total_out = 0; | ||
| pkcrypt->initialized = 0; | ||
|
|
||
| if (mz_stream_is_open(pkcrypt->stream.base) != MZ_OK) | ||
| return MZ_OPEN_ERROR; | ||
|
|
||
| if (password == NULL) | ||
| password = pkcrypt->password; | ||
| if (password == NULL) | ||
| return MZ_PARAM_ERROR; | ||
|
|
||
| mz_stream_pkcrypt_init_keys(stream, password); | ||
|
|
||
| if (mode & MZ_OPEN_MODE_WRITE) { | ||
| /* First generate RAND_HEAD_LEN - 2 random bytes. */ | ||
| mz_crypt_rand(header, MZ_PKCRYPT_HEADER_SIZE - 2); | ||
|
|
||
| /* Encrypt random header (last two bytes is high word of crc) */ | ||
| for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++) | ||
| header[i] = mz_stream_pkcrypt_encode(stream, header[i], t); | ||
|
|
||
| header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify1, t); | ||
| header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify2, t); | ||
|
|
||
| if (mz_stream_write(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header)) | ||
| return MZ_WRITE_ERROR; | ||
|
|
||
| pkcrypt->total_out += MZ_PKCRYPT_HEADER_SIZE; | ||
| } else if (mode & MZ_OPEN_MODE_READ) { | ||
| if (mz_stream_read(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header)) | ||
| return MZ_READ_ERROR; | ||
|
|
||
| for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++) | ||
| header[i] = mz_stream_pkcrypt_decode(stream, header[i]); | ||
|
|
||
| verify1 = mz_stream_pkcrypt_decode(stream, header[i++]); | ||
| verify2 = mz_stream_pkcrypt_decode(stream, header[i++]); | ||
|
|
||
| /* Older versions used 2 byte check, newer versions use 1 byte check. */ | ||
| MZ_UNUSED(verify1); | ||
| if ((verify2 != 0) && (verify2 != pkcrypt->verify2)) | ||
| return MZ_PASSWORD_ERROR; | ||
|
|
||
| pkcrypt->total_in += MZ_PKCRYPT_HEADER_SIZE; | ||
| } | ||
|
|
||
| pkcrypt->initialized = 1; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_pkcrypt_is_open(void *stream) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| if (pkcrypt->initialized == 0) | ||
| return MZ_OPEN_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| uint8_t *buf_ptr = (uint8_t *)buf; | ||
| int32_t bytes_to_read = size; | ||
| int32_t read = 0; | ||
| int32_t i = 0; | ||
|
|
||
|
|
||
| if ((int64_t)bytes_to_read > (pkcrypt->max_total_in - pkcrypt->total_in)) | ||
| bytes_to_read = (int32_t)(pkcrypt->max_total_in - pkcrypt->total_in); | ||
|
|
||
| read = mz_stream_read(pkcrypt->stream.base, buf, bytes_to_read); | ||
|
|
||
| for (i = 0; i < read; i++) | ||
| buf_ptr[i] = mz_stream_pkcrypt_decode(stream, buf_ptr[i]); | ||
|
|
||
| if (read > 0) | ||
| pkcrypt->total_in += read; | ||
|
|
||
| return read; | ||
| } | ||
|
|
||
| int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| const uint8_t *buf_ptr = (const uint8_t *)buf; | ||
| int32_t bytes_to_write = sizeof(pkcrypt->buffer); | ||
| int32_t total_written = 0; | ||
| int32_t written = 0; | ||
| int32_t i = 0; | ||
| uint16_t t = 0; | ||
|
|
||
| if (size < 0) | ||
| return MZ_PARAM_ERROR; | ||
|
|
||
| do { | ||
| if (bytes_to_write > (size - total_written)) | ||
| bytes_to_write = (size - total_written); | ||
|
|
||
| for (i = 0; i < bytes_to_write; i += 1) { | ||
| pkcrypt->buffer[i] = mz_stream_pkcrypt_encode(stream, *buf_ptr, t); | ||
| buf_ptr += 1; | ||
| } | ||
|
|
||
| written = mz_stream_write(pkcrypt->stream.base, pkcrypt->buffer, bytes_to_write); | ||
| if (written < 0) | ||
| return written; | ||
|
|
||
| total_written += written; | ||
| } while (total_written < size && written > 0); | ||
|
|
||
| pkcrypt->total_out += total_written; | ||
| return total_written; | ||
| } | ||
|
|
||
| int64_t mz_stream_pkcrypt_tell(void *stream) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| return mz_stream_tell(pkcrypt->stream.base); | ||
| } | ||
|
|
||
| int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| return mz_stream_seek(pkcrypt->stream.base, offset, origin); | ||
| } | ||
|
|
||
| int32_t mz_stream_pkcrypt_close(void *stream) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| pkcrypt->initialized = 0; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_pkcrypt_error(void *stream) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| return pkcrypt->error; | ||
| } | ||
|
|
||
| void mz_stream_pkcrypt_set_password(void *stream, const char *password) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| pkcrypt->password = password; | ||
| } | ||
|
|
||
| void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| pkcrypt->verify1 = verify1; | ||
| pkcrypt->verify2 = verify2; | ||
| } | ||
|
|
||
| void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| *verify1 = pkcrypt->verify1; | ||
| *verify2 = pkcrypt->verify2; | ||
| } | ||
|
|
||
| int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_TOTAL_IN: | ||
| *value = pkcrypt->total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_OUT: | ||
| *value = pkcrypt->total_out; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| *value = pkcrypt->max_total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_HEADER_SIZE: | ||
| *value = MZ_PKCRYPT_HEADER_SIZE; | ||
| break; | ||
| case MZ_STREAM_PROP_FOOTER_SIZE: | ||
| *value = 0; | ||
| break; | ||
| default: | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value) { | ||
| mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| pkcrypt->max_total_in = value; | ||
| break; | ||
| default: | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| void *mz_stream_pkcrypt_create(void **stream) { | ||
| mz_stream_pkcrypt *pkcrypt = NULL; | ||
|
|
||
| pkcrypt = (mz_stream_pkcrypt *)MZ_ALLOC(sizeof(mz_stream_pkcrypt)); | ||
| if (pkcrypt != NULL) { | ||
| memset(pkcrypt, 0, sizeof(mz_stream_pkcrypt)); | ||
| pkcrypt->stream.vtbl = &mz_stream_pkcrypt_vtbl; | ||
| } | ||
|
|
||
| if (stream != NULL) | ||
| *stream = pkcrypt; | ||
| return pkcrypt; | ||
| } | ||
|
|
||
| void mz_stream_pkcrypt_delete(void **stream) { | ||
| mz_stream_pkcrypt *pkcrypt = NULL; | ||
| if (stream == NULL) | ||
| return; | ||
| pkcrypt = (mz_stream_pkcrypt *)*stream; | ||
| if (pkcrypt != NULL) | ||
| MZ_FREE(pkcrypt); | ||
| *stream = NULL; | ||
| } | ||
|
|
||
| void *mz_stream_pkcrypt_get_interface(void) { | ||
| return (void *)&mz_stream_pkcrypt_vtbl; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /* mz_strm_pkcrypt.h -- Code for traditional PKWARE encryption | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
| #ifndef MZ_STREAM_PKCRYPT_H | ||
| #define MZ_STREAM_PKCRYPT_H | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_pkcrypt_open(void *stream, const char *filename, int32_t mode); | ||
| int32_t mz_stream_pkcrypt_is_open(void *stream); | ||
| int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size); | ||
| int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size); | ||
| int64_t mz_stream_pkcrypt_tell(void *stream); | ||
| int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin); | ||
| int32_t mz_stream_pkcrypt_close(void *stream); | ||
| int32_t mz_stream_pkcrypt_error(void *stream); | ||
|
|
||
| void mz_stream_pkcrypt_set_password(void *stream, const char *password); | ||
| void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2); | ||
| void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2); | ||
| int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value); | ||
| int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value); | ||
|
|
||
| void* mz_stream_pkcrypt_create(void **stream); | ||
| void mz_stream_pkcrypt_delete(void **stream); | ||
|
|
||
| void* mz_stream_pkcrypt_get_interface(void); | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* mz_strm_split.h -- Stream for split files | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
| #ifndef MZ_STREAM_SPLIT_H | ||
| #define MZ_STREAM_SPLIT_H | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_split_open(void *stream, const char *filename, int32_t mode); | ||
| int32_t mz_stream_split_is_open(void *stream); | ||
| int32_t mz_stream_split_read(void *stream, void *buf, int32_t size); | ||
| int32_t mz_stream_split_write(void *stream, const void *buf, int32_t size); | ||
| int64_t mz_stream_split_tell(void *stream); | ||
| int32_t mz_stream_split_seek(void *stream, int64_t offset, int32_t origin); | ||
| int32_t mz_stream_split_close(void *stream); | ||
| int32_t mz_stream_split_error(void *stream); | ||
|
|
||
| int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value); | ||
| int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value); | ||
|
|
||
| void* mz_stream_split_create(void **stream); | ||
| void mz_stream_split_delete(void **stream); | ||
|
|
||
| void* mz_stream_split_get_interface(void); | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,362 @@ | ||
| /* mz_strm_wzaes.c -- Stream for WinZip AES encryption | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| Copyright (C) 1998-2010 Brian Gladman, Worcester, UK | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
|
|
||
| #include "mz.h" | ||
| #include "mz_crypt.h" | ||
| #include "mz_strm.h" | ||
| #include "mz_strm_wzaes.h" | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #define MZ_AES_KEYING_ITERATIONS (1000) | ||
| #define MZ_AES_SALT_LENGTH(MODE) (4 * (MODE & 3) + 4) | ||
| #define MZ_AES_SALT_LENGTH_MAX (16) | ||
| #define MZ_AES_PW_LENGTH_MAX (128) | ||
| #define MZ_AES_PW_VERIFY_SIZE (2) | ||
| #define MZ_AES_AUTHCODE_SIZE (10) | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static mz_stream_vtbl mz_stream_wzaes_vtbl = { | ||
| mz_stream_wzaes_open, | ||
| mz_stream_wzaes_is_open, | ||
| mz_stream_wzaes_read, | ||
| mz_stream_wzaes_write, | ||
| mz_stream_wzaes_tell, | ||
| mz_stream_wzaes_seek, | ||
| mz_stream_wzaes_close, | ||
| mz_stream_wzaes_error, | ||
| mz_stream_wzaes_create, | ||
| mz_stream_wzaes_delete, | ||
| mz_stream_wzaes_get_prop_int64, | ||
| mz_stream_wzaes_set_prop_int64 | ||
| }; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| typedef struct mz_stream_wzaes_s { | ||
| mz_stream stream; | ||
| int32_t mode; | ||
| int32_t error; | ||
| int16_t initialized; | ||
| uint8_t buffer[UINT16_MAX]; | ||
| int64_t total_in; | ||
| int64_t max_total_in; | ||
| int64_t total_out; | ||
| int16_t encryption_mode; | ||
| const char *password; | ||
| void *aes; | ||
| uint32_t crypt_pos; | ||
| uint8_t crypt_block[MZ_AES_BLOCK_SIZE]; | ||
| void *hmac; | ||
| uint8_t nonce[MZ_AES_BLOCK_SIZE]; | ||
| } mz_stream_wzaes; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_wzaes_open(void *stream, const char *path, int32_t mode) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| uint16_t salt_length = 0; | ||
| uint16_t password_length = 0; | ||
| uint16_t key_length = 0; | ||
| uint8_t kbuf[2 * MZ_AES_KEY_LENGTH_MAX + MZ_AES_PW_VERIFY_SIZE]; | ||
| uint8_t verify[MZ_AES_PW_VERIFY_SIZE]; | ||
| uint8_t verify_expected[MZ_AES_PW_VERIFY_SIZE]; | ||
| uint8_t salt_value[MZ_AES_SALT_LENGTH_MAX]; | ||
| const char *password = path; | ||
|
|
||
| wzaes->total_in = 0; | ||
| wzaes->total_out = 0; | ||
| wzaes->initialized = 0; | ||
|
|
||
| if (mz_stream_is_open(wzaes->stream.base) != MZ_OK) | ||
| return MZ_OPEN_ERROR; | ||
|
|
||
| if (password == NULL) | ||
| password = wzaes->password; | ||
| if (password == NULL) | ||
| return MZ_PARAM_ERROR; | ||
| password_length = (uint16_t)strlen(password); | ||
| if (password_length > MZ_AES_PW_LENGTH_MAX) | ||
| return MZ_PARAM_ERROR; | ||
|
|
||
| if (wzaes->encryption_mode < 1 || wzaes->encryption_mode > 3) | ||
| return MZ_PARAM_ERROR; | ||
|
|
||
| salt_length = MZ_AES_SALT_LENGTH(wzaes->encryption_mode); | ||
|
|
||
| if (mode & MZ_OPEN_MODE_WRITE) { | ||
| mz_crypt_rand(salt_value, salt_length); | ||
| } else if (mode & MZ_OPEN_MODE_READ) { | ||
| if (mz_stream_read(wzaes->stream.base, salt_value, salt_length) != salt_length) | ||
| return MZ_READ_ERROR; | ||
| } | ||
|
|
||
| key_length = MZ_AES_KEY_LENGTH(wzaes->encryption_mode); | ||
|
|
||
| /* Derive the encryption and authentication keys and the password verifier */ | ||
| mz_crypt_pbkdf2((uint8_t *)password, password_length, salt_value, salt_length, | ||
| MZ_AES_KEYING_ITERATIONS, kbuf, 2 * key_length + MZ_AES_PW_VERIFY_SIZE); | ||
|
|
||
| /* Initialize the encryption nonce and buffer pos */ | ||
| wzaes->crypt_pos = MZ_AES_BLOCK_SIZE; | ||
| memset(wzaes->nonce, 0, sizeof(wzaes->nonce)); | ||
|
|
||
| /* Initialize for encryption using key 1 */ | ||
| mz_crypt_aes_reset(wzaes->aes); | ||
| mz_crypt_aes_set_mode(wzaes->aes, wzaes->encryption_mode); | ||
| mz_crypt_aes_set_encrypt_key(wzaes->aes, kbuf, key_length); | ||
|
|
||
| /* Initialize for authentication using key 2 */ | ||
| mz_crypt_hmac_reset(wzaes->hmac); | ||
| mz_crypt_hmac_set_algorithm(wzaes->hmac, MZ_HASH_SHA1); | ||
| mz_crypt_hmac_init(wzaes->hmac, kbuf + key_length, key_length); | ||
|
|
||
| memcpy(verify, kbuf + (2 * key_length), MZ_AES_PW_VERIFY_SIZE); | ||
|
|
||
| if (mode & MZ_OPEN_MODE_WRITE) { | ||
| if (mz_stream_write(wzaes->stream.base, salt_value, salt_length) != salt_length) | ||
| return MZ_WRITE_ERROR; | ||
|
|
||
| wzaes->total_out += salt_length; | ||
|
|
||
| if (mz_stream_write(wzaes->stream.base, verify, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE) | ||
| return MZ_WRITE_ERROR; | ||
|
|
||
| wzaes->total_out += MZ_AES_PW_VERIFY_SIZE; | ||
| } else if (mode & MZ_OPEN_MODE_READ) { | ||
| wzaes->total_in += salt_length; | ||
|
|
||
| if (mz_stream_read(wzaes->stream.base, verify_expected, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE) | ||
| return MZ_READ_ERROR; | ||
|
|
||
| wzaes->total_in += MZ_AES_PW_VERIFY_SIZE; | ||
|
|
||
| if (memcmp(verify_expected, verify, MZ_AES_PW_VERIFY_SIZE) != 0) | ||
| return MZ_PASSWORD_ERROR; | ||
| } | ||
|
|
||
| wzaes->mode = mode; | ||
| wzaes->initialized = 1; | ||
|
|
||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_wzaes_is_open(void *stream) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| if (wzaes->initialized == 0) | ||
| return MZ_OPEN_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| static int32_t mz_stream_wzaes_ctr_encrypt(void *stream, uint8_t *buf, int32_t size) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| uint32_t pos = wzaes->crypt_pos; | ||
| uint32_t i = 0; | ||
| int32_t err = MZ_OK; | ||
|
|
||
| while (i < (uint32_t)size) { | ||
| if (pos == MZ_AES_BLOCK_SIZE) { | ||
| uint32_t j = 0; | ||
|
|
||
| /* Increment encryption nonce */ | ||
| while (j < 8 && !++wzaes->nonce[j]) | ||
| j += 1; | ||
|
|
||
| /* Encrypt the nonce to form next xor buffer */ | ||
| memcpy(wzaes->crypt_block, wzaes->nonce, MZ_AES_BLOCK_SIZE); | ||
| mz_crypt_aes_encrypt(wzaes->aes, wzaes->crypt_block, sizeof(wzaes->crypt_block)); | ||
| pos = 0; | ||
| } | ||
|
|
||
| buf[i++] ^= wzaes->crypt_block[pos++]; | ||
| } | ||
|
|
||
| wzaes->crypt_pos = pos; | ||
| return err; | ||
| } | ||
|
|
||
| int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| int64_t max_total_in = 0; | ||
| int32_t bytes_to_read = size; | ||
| int32_t read = 0; | ||
|
|
||
| max_total_in = wzaes->max_total_in - MZ_AES_FOOTER_SIZE; | ||
| if ((int64_t)bytes_to_read > (max_total_in - wzaes->total_in)) | ||
| bytes_to_read = (int32_t)(max_total_in - wzaes->total_in); | ||
|
|
||
| read = mz_stream_read(wzaes->stream.base, buf, bytes_to_read); | ||
|
|
||
| if (read > 0) { | ||
| mz_crypt_hmac_update(wzaes->hmac, (uint8_t *)buf, read); | ||
| mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)buf, read); | ||
|
|
||
| wzaes->total_in += read; | ||
| } | ||
|
|
||
| return read; | ||
| } | ||
|
|
||
| int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| const uint8_t *buf_ptr = (const uint8_t *)buf; | ||
| int32_t bytes_to_write = sizeof(wzaes->buffer); | ||
| int32_t total_written = 0; | ||
| int32_t written = 0; | ||
|
|
||
| if (size < 0) | ||
| return MZ_PARAM_ERROR; | ||
|
|
||
| do { | ||
| if (bytes_to_write > (size - total_written)) | ||
| bytes_to_write = (size - total_written); | ||
|
|
||
| memcpy(wzaes->buffer, buf_ptr, bytes_to_write); | ||
| buf_ptr += bytes_to_write; | ||
|
|
||
| mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)wzaes->buffer, bytes_to_write); | ||
| mz_crypt_hmac_update(wzaes->hmac, wzaes->buffer, bytes_to_write); | ||
|
|
||
| written = mz_stream_write(wzaes->stream.base, wzaes->buffer, bytes_to_write); | ||
| if (written < 0) | ||
| return written; | ||
|
|
||
| total_written += written; | ||
| } while (total_written < size && written > 0); | ||
|
|
||
| wzaes->total_out += total_written; | ||
| return total_written; | ||
| } | ||
|
|
||
| int64_t mz_stream_wzaes_tell(void *stream) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| return mz_stream_tell(wzaes->stream.base); | ||
| } | ||
|
|
||
| int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| return mz_stream_seek(wzaes->stream.base, offset, origin); | ||
| } | ||
|
|
||
| int32_t mz_stream_wzaes_close(void *stream) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| uint8_t expected_hash[MZ_AES_AUTHCODE_SIZE]; | ||
| uint8_t computed_hash[MZ_HASH_SHA1_SIZE]; | ||
|
|
||
| mz_crypt_hmac_end(wzaes->hmac, computed_hash, sizeof(computed_hash)); | ||
|
|
||
| if (wzaes->mode & MZ_OPEN_MODE_WRITE) { | ||
| if (mz_stream_write(wzaes->stream.base, computed_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE) | ||
| return MZ_WRITE_ERROR; | ||
|
|
||
| wzaes->total_out += MZ_AES_AUTHCODE_SIZE; | ||
| } else if (wzaes->mode & MZ_OPEN_MODE_READ) { | ||
| if (mz_stream_read(wzaes->stream.base, expected_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE) | ||
| return MZ_READ_ERROR; | ||
|
|
||
| wzaes->total_in += MZ_AES_AUTHCODE_SIZE; | ||
|
|
||
| /* If entire entry was not read this will fail */ | ||
| if (memcmp(computed_hash, expected_hash, MZ_AES_AUTHCODE_SIZE) != 0) | ||
| return MZ_CRC_ERROR; | ||
| } | ||
|
|
||
| wzaes->initialized = 0; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_wzaes_error(void *stream) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| return wzaes->error; | ||
| } | ||
|
|
||
| void mz_stream_wzaes_set_password(void *stream, const char *password) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| wzaes->password = password; | ||
| } | ||
|
|
||
| void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| wzaes->encryption_mode = encryption_mode; | ||
| } | ||
|
|
||
| int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_TOTAL_IN: | ||
| *value = wzaes->total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_OUT: | ||
| *value = wzaes->total_out; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| *value = wzaes->max_total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_HEADER_SIZE: | ||
| *value = MZ_AES_SALT_LENGTH((int64_t)wzaes->encryption_mode) + MZ_AES_PW_VERIFY_SIZE; | ||
| break; | ||
| case MZ_STREAM_PROP_FOOTER_SIZE: | ||
| *value = MZ_AES_AUTHCODE_SIZE; | ||
| break; | ||
| default: | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value) { | ||
| mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| wzaes->max_total_in = value; | ||
| break; | ||
| default: | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| void *mz_stream_wzaes_create(void **stream) { | ||
| mz_stream_wzaes *wzaes = NULL; | ||
|
|
||
| wzaes = (mz_stream_wzaes *)MZ_ALLOC(sizeof(mz_stream_wzaes)); | ||
| if (wzaes != NULL) { | ||
| memset(wzaes, 0, sizeof(mz_stream_wzaes)); | ||
| wzaes->stream.vtbl = &mz_stream_wzaes_vtbl; | ||
| wzaes->encryption_mode = MZ_AES_ENCRYPTION_MODE_256; | ||
|
|
||
| mz_crypt_hmac_create(&wzaes->hmac); | ||
| mz_crypt_aes_create(&wzaes->aes); | ||
| } | ||
| if (stream != NULL) | ||
| *stream = wzaes; | ||
|
|
||
| return wzaes; | ||
| } | ||
|
|
||
| void mz_stream_wzaes_delete(void **stream) { | ||
| mz_stream_wzaes *wzaes = NULL; | ||
| if (stream == NULL) | ||
| return; | ||
| wzaes = (mz_stream_wzaes *)*stream; | ||
| if (wzaes != NULL) { | ||
| mz_crypt_aes_delete(&wzaes->aes); | ||
| mz_crypt_hmac_delete(&wzaes->hmac); | ||
| MZ_FREE(wzaes); | ||
| } | ||
| *stream = NULL; | ||
| } | ||
|
|
||
| void *mz_stream_wzaes_get_interface(void) { | ||
| return (void *)&mz_stream_wzaes_vtbl; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /* mz_strm_wzaes.h -- Stream for WinZIP AES encryption | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
| #ifndef MZ_STREAM_WZAES_SHA1_H | ||
| #define MZ_STREAM_WZAES_SHA1_H | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_wzaes_open(void *stream, const char *filename, int32_t mode); | ||
| int32_t mz_stream_wzaes_is_open(void *stream); | ||
| int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size); | ||
| int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size); | ||
| int64_t mz_stream_wzaes_tell(void *stream); | ||
| int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin); | ||
| int32_t mz_stream_wzaes_close(void *stream); | ||
| int32_t mz_stream_wzaes_error(void *stream); | ||
|
|
||
| void mz_stream_wzaes_set_password(void *stream, const char *password); | ||
| void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode); | ||
|
|
||
| int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value); | ||
| int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value); | ||
|
|
||
| void* mz_stream_wzaes_create(void **stream); | ||
| void mz_stream_wzaes_delete(void **stream); | ||
|
|
||
| void* mz_stream_wzaes_get_interface(void); | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,393 @@ | ||
| /* mz_strm_zlib.c -- Stream for zlib inflate/deflate | ||
| part of the minizip-ng project | ||
| Copyright (C) 2010-2021 Nathan Moinvaziri | ||
| https://github.com/zlib-ng/minizip-ng | ||
| This program is distributed under the terms of the same license as zlib. | ||
| See the accompanying LICENSE file for the full text of the license. | ||
| */ | ||
|
|
||
|
|
||
| #include "mz.h" | ||
| #include "mz_strm.h" | ||
| #include "mz_strm_zlib.h" | ||
|
|
||
| #include "zlib.h" | ||
| #if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT) | ||
| # include "zlib-ng.h" | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| #if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT) | ||
| # define ZLIB_PREFIX(x) zng_ ## x | ||
| typedef zng_stream zlib_stream; | ||
| #else | ||
| # define ZLIB_PREFIX(x) x | ||
| typedef z_stream zlib_stream; | ||
| #endif | ||
|
|
||
| #if !defined(DEF_MEM_LEVEL) | ||
| # if MAX_MEM_LEVEL >= 8 | ||
| # define DEF_MEM_LEVEL 8 | ||
| # else | ||
| # define DEF_MEM_LEVEL MAX_MEM_LEVEL | ||
| # endif | ||
| #endif | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| static mz_stream_vtbl mz_stream_zlib_vtbl = { | ||
| mz_stream_zlib_open, | ||
| mz_stream_zlib_is_open, | ||
| mz_stream_zlib_read, | ||
| mz_stream_zlib_write, | ||
| mz_stream_zlib_tell, | ||
| mz_stream_zlib_seek, | ||
| mz_stream_zlib_close, | ||
| mz_stream_zlib_error, | ||
| mz_stream_zlib_create, | ||
| mz_stream_zlib_delete, | ||
| mz_stream_zlib_get_prop_int64, | ||
| mz_stream_zlib_set_prop_int64 | ||
| }; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| typedef struct mz_stream_zlib_s { | ||
| mz_stream stream; | ||
| zlib_stream zstream; | ||
| uint8_t buffer[INT16_MAX]; | ||
| int32_t buffer_len; | ||
| int64_t total_in; | ||
| int64_t total_out; | ||
| int64_t max_total_in; | ||
| int8_t initialized; | ||
| int16_t level; | ||
| int32_t window_bits; | ||
| int32_t mode; | ||
| int32_t error; | ||
| } mz_stream_zlib; | ||
|
|
||
| /***************************************************************************/ | ||
|
|
||
| int32_t mz_stream_zlib_open(void *stream, const char *path, int32_t mode) { | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
|
|
||
| MZ_UNUSED(path); | ||
|
|
||
| zlib->zstream.data_type = Z_BINARY; | ||
| zlib->zstream.zalloc = Z_NULL; | ||
| zlib->zstream.zfree = Z_NULL; | ||
| zlib->zstream.opaque = Z_NULL; | ||
| zlib->zstream.total_in = 0; | ||
| zlib->zstream.total_out = 0; | ||
|
|
||
| zlib->total_in = 0; | ||
| zlib->total_out = 0; | ||
|
|
||
| if (mode & MZ_OPEN_MODE_WRITE) { | ||
| #ifdef MZ_ZIP_NO_COMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| zlib->zstream.next_out = zlib->buffer; | ||
| zlib->zstream.avail_out = sizeof(zlib->buffer); | ||
|
|
||
| zlib->error = ZLIB_PREFIX(deflateInit2)(&zlib->zstream, (int8_t)zlib->level, Z_DEFLATED, | ||
| zlib->window_bits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); | ||
| #endif | ||
| } else if (mode & MZ_OPEN_MODE_READ) { | ||
| #ifdef MZ_ZIP_NO_DECOMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| zlib->zstream.next_in = zlib->buffer; | ||
| zlib->zstream.avail_in = 0; | ||
|
|
||
| zlib->error = ZLIB_PREFIX(inflateInit2)(&zlib->zstream, zlib->window_bits); | ||
| #endif | ||
| } | ||
|
|
||
| if (zlib->error != Z_OK) | ||
| return MZ_OPEN_ERROR; | ||
|
|
||
| zlib->initialized = 1; | ||
| zlib->mode = mode; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_zlib_is_open(void *stream) { | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
| if (zlib->initialized != 1) | ||
| return MZ_OPEN_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size) { | ||
| #ifdef MZ_ZIP_NO_DECOMPRESSION | ||
| MZ_UNUSED(stream); | ||
| MZ_UNUSED(buf); | ||
| MZ_UNUSED(size); | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
| uint64_t total_in_before = 0; | ||
| uint64_t total_in_after = 0; | ||
| uint64_t total_out_before = 0; | ||
| uint64_t total_out_after = 0; | ||
| uint32_t total_in = 0; | ||
| uint32_t total_out = 0; | ||
| uint32_t in_bytes = 0; | ||
| uint32_t out_bytes = 0; | ||
| int32_t bytes_to_read = sizeof(zlib->buffer); | ||
| int32_t read = 0; | ||
| int32_t err = Z_OK; | ||
|
|
||
|
|
||
| zlib->zstream.next_out = (Bytef*)buf; | ||
| zlib->zstream.avail_out = (uInt)size; | ||
|
|
||
| do { | ||
| if (zlib->zstream.avail_in == 0) { | ||
| if (zlib->max_total_in > 0) { | ||
| if ((int64_t)bytes_to_read > (zlib->max_total_in - zlib->total_in)) | ||
| bytes_to_read = (int32_t)(zlib->max_total_in - zlib->total_in); | ||
| } | ||
|
|
||
| read = mz_stream_read(zlib->stream.base, zlib->buffer, bytes_to_read); | ||
|
|
||
| if (read < 0) | ||
| return read; | ||
|
|
||
| zlib->zstream.next_in = zlib->buffer; | ||
| zlib->zstream.avail_in = read; | ||
| } | ||
|
|
||
| total_in_before = zlib->zstream.avail_in; | ||
| total_out_before = zlib->zstream.total_out; | ||
|
|
||
| err = ZLIB_PREFIX(inflate)(&zlib->zstream, Z_SYNC_FLUSH); | ||
| if ((err >= Z_OK) && (zlib->zstream.msg != NULL)) { | ||
| zlib->error = Z_DATA_ERROR; | ||
| break; | ||
| } | ||
|
|
||
| total_in_after = zlib->zstream.avail_in; | ||
| total_out_after = zlib->zstream.total_out; | ||
|
|
||
| in_bytes = (uint32_t)(total_in_before - total_in_after); | ||
| out_bytes = (uint32_t)(total_out_after - total_out_before); | ||
|
|
||
| total_in += in_bytes; | ||
| total_out += out_bytes; | ||
|
|
||
| zlib->total_in += in_bytes; | ||
| zlib->total_out += out_bytes; | ||
|
|
||
| if (err == Z_STREAM_END) | ||
| break; | ||
| if (err != Z_OK) { | ||
| zlib->error = err; | ||
| break; | ||
| } | ||
| } while (zlib->zstream.avail_out > 0); | ||
|
|
||
| if (zlib->error != 0) { | ||
| /* Zlib errors are compatible with MZ */ | ||
| return zlib->error; | ||
| } | ||
|
|
||
| return total_out; | ||
| #endif | ||
| } | ||
|
|
||
| #ifndef MZ_ZIP_NO_COMPRESSION | ||
| static int32_t mz_stream_zlib_flush(void *stream) { | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
| if (mz_stream_write(zlib->stream.base, zlib->buffer, zlib->buffer_len) != zlib->buffer_len) | ||
| return MZ_WRITE_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| static int32_t mz_stream_zlib_deflate(void *stream, int flush) { | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
| uint64_t total_out_before = 0; | ||
| uint64_t total_out_after = 0; | ||
| int32_t out_bytes = 0; | ||
| int32_t err = Z_OK; | ||
|
|
||
|
|
||
| do { | ||
| if (zlib->zstream.avail_out == 0) { | ||
| err = mz_stream_zlib_flush(zlib); | ||
| if (err != MZ_OK) | ||
| return err; | ||
|
|
||
| zlib->zstream.avail_out = sizeof(zlib->buffer); | ||
| zlib->zstream.next_out = zlib->buffer; | ||
|
|
||
| zlib->buffer_len = 0; | ||
| } | ||
|
|
||
| total_out_before = zlib->zstream.total_out; | ||
| err = ZLIB_PREFIX(deflate)(&zlib->zstream, flush); | ||
| total_out_after = zlib->zstream.total_out; | ||
|
|
||
| out_bytes = (uint32_t)(total_out_after - total_out_before); | ||
|
|
||
| zlib->buffer_len += out_bytes; | ||
| zlib->total_out += out_bytes; | ||
|
|
||
| if (err == Z_STREAM_END) | ||
| break; | ||
| if (err != Z_OK) { | ||
| zlib->error = err; | ||
| return MZ_DATA_ERROR; | ||
| } | ||
| } while ((zlib->zstream.avail_in > 0) || (flush == Z_FINISH && err == Z_OK)); | ||
|
|
||
| return MZ_OK; | ||
| } | ||
| #endif | ||
|
|
||
| int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size) { | ||
| #ifdef MZ_ZIP_NO_COMPRESSION | ||
| MZ_UNUSED(stream); | ||
| MZ_UNUSED(buf); | ||
| MZ_UNUSED(size); | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
| int32_t err = MZ_OK; | ||
|
|
||
| zlib->zstream.next_in = (Bytef*)(intptr_t)buf; | ||
| zlib->zstream.avail_in = (uInt)size; | ||
|
|
||
| err = mz_stream_zlib_deflate(stream, Z_NO_FLUSH); | ||
| if (err != MZ_OK) { | ||
| return err; | ||
| } | ||
|
|
||
| zlib->total_in += size; | ||
| return size; | ||
| #endif | ||
| } | ||
|
|
||
| int64_t mz_stream_zlib_tell(void *stream) { | ||
| MZ_UNUSED(stream); | ||
|
|
||
| return MZ_TELL_ERROR; | ||
| } | ||
|
|
||
| int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin) { | ||
| MZ_UNUSED(stream); | ||
| MZ_UNUSED(offset); | ||
| MZ_UNUSED(origin); | ||
|
|
||
| return MZ_SEEK_ERROR; | ||
| } | ||
|
|
||
| int32_t mz_stream_zlib_close(void *stream) { | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
|
|
||
|
|
||
| if (zlib->mode & MZ_OPEN_MODE_WRITE) { | ||
| #ifdef MZ_ZIP_NO_COMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| mz_stream_zlib_deflate(stream, Z_FINISH); | ||
| mz_stream_zlib_flush(stream); | ||
|
|
||
| ZLIB_PREFIX(deflateEnd)(&zlib->zstream); | ||
| #endif | ||
| } else if (zlib->mode & MZ_OPEN_MODE_READ) { | ||
| #ifdef MZ_ZIP_NO_DECOMPRESSION | ||
| return MZ_SUPPORT_ERROR; | ||
| #else | ||
| ZLIB_PREFIX(inflateEnd)(&zlib->zstream); | ||
| #endif | ||
| } | ||
|
|
||
| zlib->initialized = 0; | ||
|
|
||
| if (zlib->error != Z_OK) | ||
| return MZ_CLOSE_ERROR; | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_zlib_error(void *stream) { | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
| return zlib->error; | ||
| } | ||
|
|
||
| int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value) { | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_TOTAL_IN: | ||
| *value = zlib->total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| *value = zlib->max_total_in; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_OUT: | ||
| *value = zlib->total_out; | ||
| break; | ||
| case MZ_STREAM_PROP_HEADER_SIZE: | ||
| *value = 0; | ||
| break; | ||
| case MZ_STREAM_PROP_COMPRESS_WINDOW: | ||
| *value = zlib->window_bits; | ||
| break; | ||
| default: | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value) { | ||
| mz_stream_zlib *zlib = (mz_stream_zlib *)stream; | ||
| switch (prop) { | ||
| case MZ_STREAM_PROP_COMPRESS_LEVEL: | ||
| zlib->level = (int16_t)value; | ||
| break; | ||
| case MZ_STREAM_PROP_TOTAL_IN_MAX: | ||
| zlib->max_total_in = value; | ||
| break; | ||
| case MZ_STREAM_PROP_COMPRESS_WINDOW: | ||
| zlib->window_bits = (int32_t)value; | ||
| break; | ||
| default: | ||
| return MZ_EXIST_ERROR; | ||
| } | ||
| return MZ_OK; | ||
| } | ||
|
|
||
| void *mz_stream_zlib_create(void **stream) { | ||
| mz_stream_zlib *zlib = NULL; | ||
|
|
||
| zlib = (mz_stream_zlib *)MZ_ALLOC(sizeof(mz_stream_zlib)); | ||
| if (zlib != NULL) { | ||
| memset(zlib, 0, sizeof(mz_stream_zlib)); | ||
| zlib->stream.vtbl = &mz_stream_zlib_vtbl; | ||
| zlib->level = Z_DEFAULT_COMPRESSION; | ||
| zlib->window_bits = -MAX_WBITS; | ||
| } | ||
| if (stream != NULL) | ||
| *stream = zlib; | ||
|
|
||
| return zlib; | ||
| } | ||
|
|
||
| void mz_stream_zlib_delete(void **stream) { | ||
| mz_stream_zlib *zlib = NULL; | ||
| if (stream == NULL) | ||
| return; | ||
| zlib = (mz_stream_zlib *)*stream; | ||
| if (zlib != NULL) | ||
| MZ_FREE(zlib); | ||
| *stream = NULL; | ||
| } | ||
|
|
||
| void *mz_stream_zlib_get_interface(void) { | ||
| return (void *)&mz_stream_zlib_vtbl; | ||
| } |