Large diffs are not rendered by default.

@@ -14,4 +14,4 @@ freely, subject to the following restrictions:
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
3. This notice may not be removed or altered from any source distribution.
@@ -1,2 +1,3 @@
Partial import from https://github.com/nmoinvaz/minizip
Revision: b3713abe7722f1b779e7cdbd527c6208abbe1121
minizip-ng, Version 3.0.4 (2021-11-29)
https://github.com/zlib-ng/minizip-ng
Revision: 95987e98b4862c055b8cf91d6e7ce5f9153ddc24

This file was deleted.

This file was deleted.

@@ -0,0 +1,182 @@
/* minigzip.c
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_os.h"
#include "mz_strm.h"
#include "mz_strm_os.h"
#include "mz_strm_zlib.h"

#include <stdio.h> /* printf */

/***************************************************************************/

#define MZ_GZIP_COMPRESS (1)
#define MZ_GZIP_DECOMPRESS (2)

int32_t minigzip_banner(void);
int32_t minigzip_help(void);

/***************************************************************************/

int32_t minigzip_banner(void) {
printf("Minigzip %s - https://github.com/zlib-ng/minizip-ng\n", MZ_VERSION);
printf("---------------------------------------------------\n");
return MZ_OK;
}

int32_t minigzip_help(void) {
printf("Usage: minigzip [-x] [-d] [-0 to -9] [files]\n\n" \
" -x Extract file\n" \
" -d Destination directory\n" \
" -0 Store only\n" \
" -1 Compress faster\n" \
" -9 Compress better\n\n");
return MZ_OK;
}

/***************************************************************************/

int32_t minigzip_copy(const char *path, const char *destination, int16_t operation, int16_t level) {
void *target_stream = NULL;
void *source_stream = NULL;
void *zlib_stream = NULL;
const char *filename = NULL;
char target_path[1024];
int32_t err = 0;


memset(target_path, 0, sizeof(target_path));

if (destination != NULL) {
if (mz_os_file_exists(destination) != MZ_OK)
mz_dir_make(destination);
}

if (operation == MZ_GZIP_COMPRESS) {
mz_path_combine(target_path, path, sizeof(target_path));
strncat(target_path, ".gz", sizeof(target_path) - strlen(target_path) - 1);
printf("Compressing to %s\n", target_path);
} else if (operation == MZ_GZIP_DECOMPRESS) {
if (destination != NULL)
mz_path_combine(target_path, destination, sizeof(target_path));

if (mz_path_get_filename(path, &filename) != MZ_OK)
filename = path;

mz_path_combine(target_path, filename, sizeof(target_path));
mz_path_remove_extension(target_path);
printf("Decompressing to %s\n", target_path);
}

mz_stream_zlib_create(&zlib_stream);
mz_stream_zlib_set_prop_int64(zlib_stream, MZ_STREAM_PROP_COMPRESS_WINDOW, 15 + 16);

mz_stream_os_create(&source_stream);
err = mz_stream_os_open(source_stream, path, MZ_OPEN_MODE_READ);

if (err == MZ_OK) {
mz_stream_os_create(&target_stream);
err = mz_stream_os_open(target_stream, target_path, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE);

if (err == MZ_OK) {
if (operation == MZ_GZIP_COMPRESS) {
mz_stream_zlib_set_prop_int64(zlib_stream, MZ_STREAM_PROP_COMPRESS_LEVEL, level);
mz_stream_zlib_open(zlib_stream, target_path, MZ_OPEN_MODE_WRITE);
mz_stream_set_base(zlib_stream, target_stream);
err = mz_stream_copy_to_end(zlib_stream, source_stream);
} else if (operation == MZ_GZIP_DECOMPRESS) {
mz_stream_zlib_open(zlib_stream, path, MZ_OPEN_MODE_READ);
mz_stream_set_base(zlib_stream, source_stream);
err = mz_stream_copy_to_end(target_stream, zlib_stream);
}

if (err != MZ_OK)
printf("Error %d in zlib stream (%d)\n", err, mz_stream_zlib_error(zlib_stream));
else
printf("Operation completed successfully\n");

mz_stream_zlib_close(zlib_stream);
} else {
printf("Error %d opening target path %s\n", err, target_path);
}

mz_stream_os_close(target_stream);
mz_stream_os_delete(&target_stream);
} else {
printf("Error %d opening source path %s\n", err, path);
}

mz_stream_os_close(source_stream);
mz_stream_os_delete(&source_stream);

mz_stream_zlib_delete(&zlib_stream);
return err;
}

/***************************************************************************/

#if !defined(MZ_ZIP_NO_MAIN)
int main(int argc, const char *argv[]) {
int16_t operation_level = MZ_COMPRESS_LEVEL_DEFAULT;
int32_t path_arg = 0;
int32_t err = 0;
int32_t i = 0;
uint8_t operation = MZ_GZIP_COMPRESS;
const char *path = NULL;
const char *destination = NULL;


minigzip_banner();
if (argc == 1) {
minigzip_help();
return 0;
}

/* Parse command line options */
for (i = 1; i < argc; i += 1) {
printf("%s ", argv[i]);
if (argv[i][0] == '-') {
char c = argv[i][1];
if ((c == 'x') || (c == 'X'))
operation = MZ_GZIP_DECOMPRESS;
else if ((c >= '0') && (c <= '9'))
operation_level = (c - '0');
else if (((c == 'd') || (c == 'D')) && (i + 1 < argc)) {
destination = argv[i + 1];
printf("%s ", argv[i + 1]);
i += 1;
} else {
err = MZ_SUPPORT_ERROR;
}
} else if (path_arg == 0) {
path_arg = i;
break;
}
}
printf("\n");

if (err == MZ_SUPPORT_ERROR) {
printf("Feature not supported\n");
return err;
}

if (path_arg == 0) {
minigzip_help();
return 0;
}

path = argv[path_arg];
err = minigzip_copy(path, destination, operation, operation_level);

return err;
}
#endif

Large diffs are not rendered by default.

@@ -0,0 +1,14 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
sharedlibdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@

Name: @PROJECT_NAME@
Description: Minizip zip file manipulation library
Version: @VERSION@

Requires: zlib
Libs: -L${libdir} -L${sharedlibdir} -l@PROJECT_NAME@
Libs.private:@PC_PRIVATE_LIBS@
Cflags: -I${includedir}
@@ -17,19 +17,41 @@
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>NOUNCRYPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>HAVE_ZLIB;ZLIB_COMPAT;MZ_ZIP_NO_CRYPTO;MZ_ZIP_NO_ENCRYPTION;HAVE_STDINT_H;HAVE_INTTYPES_H;NO_FSEEKO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ioapi.c" />
<ClCompile Include="unzip.c" />
<ClCompile Include="mz_compat.c" />
<ClCompile Include="mz_crypt.c" />
<ClCompile Include="mz_os.c" />
<ClCompile Include="mz_os_win32.c" />
<ClCompile Include="mz_strm.c" />
<ClCompile Include="mz_strm_buf.c" />
<ClCompile Include="mz_strm_mem.c" />
<ClCompile Include="mz_strm_os_win32.c" />
<ClCompile Include="mz_strm_split.c" />
<ClCompile Include="mz_strm_zlib.c" />
<ClCompile Include="mz_zip.c" />
<ClCompile Include="mz_zip_rw.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ioapi.h" />
<ClInclude Include="mz.h" />
<ClInclude Include="mz_compat.h" />
<ClInclude Include="mz_crypt.h" />
<ClInclude Include="mz_os.h" />
<ClInclude Include="mz_strm.h" />
<ClInclude Include="mz_strm_buf.h" />
<ClInclude Include="mz_strm_mem.h" />
<ClInclude Include="mz_strm_os.h" />
<ClInclude Include="mz_strm_split.h" />
<ClInclude Include="mz_strm_zlib.h" />
<ClInclude Include="mz_zip.h" />
<ClInclude Include="mz_zip_rw.h" />
<ClInclude Include="unzip.h" />
<ClInclude Include="zip.h" />
</ItemGroup>
<ItemGroup>
<None Include="LICENSE" />
@@ -0,0 +1,274 @@
/* mz.h -- Errors codes, zip flags and magic
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_H
#define MZ_H

/***************************************************************************/

/* MZ_VERSION */
#define MZ_VERSION ("3.0.4")
#define MZ_VERSION_BUILD (030004)

/* MZ_ERROR */
#define MZ_OK (0) /* zlib */
#define MZ_STREAM_ERROR (-1) /* zlib */
#define MZ_DATA_ERROR (-3) /* zlib */
#define MZ_MEM_ERROR (-4) /* zlib */
#define MZ_BUF_ERROR (-5) /* zlib */
#define MZ_VERSION_ERROR (-6) /* zlib */

#define MZ_END_OF_LIST (-100)
#define MZ_END_OF_STREAM (-101)

#define MZ_PARAM_ERROR (-102)
#define MZ_FORMAT_ERROR (-103)
#define MZ_INTERNAL_ERROR (-104)
#define MZ_CRC_ERROR (-105)
#define MZ_CRYPT_ERROR (-106)
#define MZ_EXIST_ERROR (-107)
#define MZ_PASSWORD_ERROR (-108)
#define MZ_SUPPORT_ERROR (-109)
#define MZ_HASH_ERROR (-110)
#define MZ_OPEN_ERROR (-111)
#define MZ_CLOSE_ERROR (-112)
#define MZ_SEEK_ERROR (-113)
#define MZ_TELL_ERROR (-114)
#define MZ_READ_ERROR (-115)
#define MZ_WRITE_ERROR (-116)
#define MZ_SIGN_ERROR (-117)
#define MZ_SYMLINK_ERROR (-118)

/* MZ_OPEN */
#define MZ_OPEN_MODE_READ (0x01)
#define MZ_OPEN_MODE_WRITE (0x02)
#define MZ_OPEN_MODE_READWRITE (MZ_OPEN_MODE_READ | MZ_OPEN_MODE_WRITE)
#define MZ_OPEN_MODE_APPEND (0x04)
#define MZ_OPEN_MODE_CREATE (0x08)
#define MZ_OPEN_MODE_EXISTING (0x10)

/* MZ_SEEK */
#define MZ_SEEK_SET (0)
#define MZ_SEEK_CUR (1)
#define MZ_SEEK_END (2)

/* MZ_COMPRESS */
#define MZ_COMPRESS_METHOD_STORE (0)
#define MZ_COMPRESS_METHOD_DEFLATE (8)
#define MZ_COMPRESS_METHOD_BZIP2 (12)
#define MZ_COMPRESS_METHOD_LZMA (14)
#define MZ_COMPRESS_METHOD_ZSTD (93)
#define MZ_COMPRESS_METHOD_XZ (95)
#define MZ_COMPRESS_METHOD_AES (99)

#define MZ_COMPRESS_LEVEL_DEFAULT (-1)
#define MZ_COMPRESS_LEVEL_FAST (2)
#define MZ_COMPRESS_LEVEL_NORMAL (6)
#define MZ_COMPRESS_LEVEL_BEST (9)

/* MZ_ZIP_FLAG */
#define MZ_ZIP_FLAG_ENCRYPTED (1 << 0)
#define MZ_ZIP_FLAG_LZMA_EOS_MARKER (1 << 1)
#define MZ_ZIP_FLAG_DEFLATE_MAX (1 << 1)
#define MZ_ZIP_FLAG_DEFLATE_NORMAL (0)
#define MZ_ZIP_FLAG_DEFLATE_FAST (1 << 2)
#define MZ_ZIP_FLAG_DEFLATE_SUPER_FAST (MZ_ZIP_FLAG_DEFLATE_FAST | \
MZ_ZIP_FLAG_DEFLATE_MAX)
#define MZ_ZIP_FLAG_DATA_DESCRIPTOR (1 << 3)
#define MZ_ZIP_FLAG_UTF8 (1 << 11)
#define MZ_ZIP_FLAG_MASK_LOCAL_INFO (1 << 13)

/* MZ_ZIP_EXTENSION */
#define MZ_ZIP_EXTENSION_ZIP64 (0x0001)
#define MZ_ZIP_EXTENSION_NTFS (0x000a)
#define MZ_ZIP_EXTENSION_AES (0x9901)
#define MZ_ZIP_EXTENSION_UNIX1 (0x000d)
#define MZ_ZIP_EXTENSION_SIGN (0x10c5)
#define MZ_ZIP_EXTENSION_HASH (0x1a51)
#define MZ_ZIP_EXTENSION_CDCD (0xcdcd)

/* MZ_ZIP64 */
#define MZ_ZIP64_AUTO (0)
#define MZ_ZIP64_FORCE (1)
#define MZ_ZIP64_DISABLE (2)

/* MZ_HOST_SYSTEM */
#define MZ_HOST_SYSTEM(VERSION_MADEBY) ((uint8_t)(VERSION_MADEBY >> 8))
#define MZ_HOST_SYSTEM_MSDOS (0)
#define MZ_HOST_SYSTEM_UNIX (3)
#define MZ_HOST_SYSTEM_WINDOWS_NTFS (10)
#define MZ_HOST_SYSTEM_RISCOS (13)
#define MZ_HOST_SYSTEM_OSX_DARWIN (19)

/* MZ_PKCRYPT */
#define MZ_PKCRYPT_HEADER_SIZE (12)

/* MZ_AES */
#define MZ_AES_VERSION (1)
#define MZ_AES_ENCRYPTION_MODE_128 (0x01)
#define MZ_AES_ENCRYPTION_MODE_192 (0x02)
#define MZ_AES_ENCRYPTION_MODE_256 (0x03)
#define MZ_AES_KEY_LENGTH(MODE) (8 * (MODE & 3) + 8)
#define MZ_AES_KEY_LENGTH_MAX (32)
#define MZ_AES_BLOCK_SIZE (16)
#define MZ_AES_HEADER_SIZE(MODE) ((4 * (MODE & 3) + 4) + 2)
#define MZ_AES_FOOTER_SIZE (10)

/* MZ_HASH */
#define MZ_HASH_MD5 (10)
#define MZ_HASH_MD5_SIZE (16)
#define MZ_HASH_SHA1 (20)
#define MZ_HASH_SHA1_SIZE (20)
#define MZ_HASH_SHA256 (23)
#define MZ_HASH_SHA256_SIZE (32)
#define MZ_HASH_MAX_SIZE (256)

/* MZ_ENCODING */
#define MZ_ENCODING_CODEPAGE_437 (437)
#define MZ_ENCODING_CODEPAGE_932 (932)
#define MZ_ENCODING_CODEPAGE_936 (936)
#define MZ_ENCODING_CODEPAGE_950 (950)
#define MZ_ENCODING_UTF8 (65001)

/* MZ_UTILITY */
#define MZ_UNUSED(SYMBOL) ((void)SYMBOL)

#ifndef MZ_CUSTOM_ALLOC
#define MZ_ALLOC(SIZE) (malloc((SIZE)))
#endif
#ifndef MZ_CUSTOM_FREE
#define MZ_FREE(PTR) (free(PTR))
#endif

#if defined(_WIN32) && defined(MZ_EXPORTS)
#define MZ_EXPORT __declspec(dllexport)
#else
#define MZ_EXPORT
#endif

/***************************************************************************/

#include <stdlib.h> /* size_t, NULL, malloc */
#include <time.h> /* time_t, time() */
#include <string.h> /* memset, strncpy, strlen */
#include <limits.h>

#if defined(HAVE_STDINT_H)
# include <stdint.h>
#elif defined(__has_include)
# if __has_include(<stdint.h>)
# include <stdint.h>
# endif
#endif

#ifndef INT8_MAX
typedef signed char int8_t;
#endif
#ifndef INT16_MAX
typedef short int16_t;
#endif
#ifndef INT32_MAX
typedef int int32_t;
#endif
#ifndef INT64_MAX
typedef long long int64_t;
#endif
#ifndef UINT8_MAX
typedef unsigned char uint8_t;
#endif
#ifndef UINT16_MAX
typedef unsigned short uint16_t;
#endif
#ifndef UINT32_MAX
typedef unsigned int uint32_t;
#endif
#ifndef UINT64_MAX
typedef unsigned long long uint64_t;
#endif

#if defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#elif defined(__has_include)
# if __has_include(<inttypes.h>)
# include <inttypes.h>
# endif
#endif

#ifndef PRId8
# define PRId8 "hhd"
#endif
#ifndef PRIu8
# define PRIu8 "hhu"
#endif
#ifndef PRIx8
# define PRIx8 "hhx"
#endif
#ifndef PRId16
# define PRId16 "hd"
#endif
#ifndef PRIu16
# define PRIu16 "hu"
#endif
#ifndef PRIx16
# define PRIx16 "hx"
#endif
#ifndef PRId32
# define PRId32 "d"
#endif
#ifndef PRIu32
# define PRIu32 "u"
#endif
#ifndef PRIx32
# define PRIx32 "x"
#endif
#if ULONG_MAX == 0xfffffffful
# ifndef PRId64
# define PRId64 "ld"
# endif
# ifndef PRIu64
# define PRIu64 "lu"
# endif
# ifndef PRIx64
# define PRIx64 "lx"
# endif
#else
# ifndef PRId64
# define PRId64 "lld"
# endif
# ifndef PRIu64
# define PRIu64 "llu"
# endif
# ifndef PRIx64
# define PRIx64 "llx"
# endif
#endif

#ifndef INT16_MAX
# define INT16_MAX 32767
#endif
#ifndef INT32_MAX
# define INT32_MAX 2147483647L
#endif
#ifndef INT64_MAX
# define INT64_MAX 9223372036854775807LL
#endif
#ifndef UINT16_MAX
# define UINT16_MAX 65535U
#endif
#ifndef UINT32_MAX
# define UINT32_MAX 4294967295UL
#endif
#ifndef UINT64_MAX
# define UINT64_MAX 18446744073709551615ULL
#endif

/***************************************************************************/

#endif

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -0,0 +1,196 @@
/* mz_crypt.c -- Crypto/hash functions
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_os.h"
#include "mz_crypt.h"

#if defined(HAVE_ZLIB)
# include "zlib.h"
# if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
# include "zlib-ng.h"
# endif
#elif defined(HAVE_LZMA)
# include "lzma.h"
#endif

/***************************************************************************/
/* Define z_crc_t in zlib 1.2.5 and less or if using zlib-ng */

#if defined(HAVE_ZLIB) && defined(ZLIBNG_VERNUM)
# if defined(ZLIB_COMPAT)
# define ZLIB_PREFIX(x) x
# else
# define ZLIB_PREFIX(x) zng_ ## x
# endif
typedef uint32_t z_crc_t;
#elif defined(HAVE_ZLIB)
# define ZLIB_PREFIX(x) x
# if (ZLIB_VERNUM < 0x1270)
typedef unsigned long z_crc_t;
# endif
#endif

/***************************************************************************/

#if defined(MZ_ZIP_NO_CRYPTO)
int32_t mz_crypt_rand(uint8_t *buf, int32_t size) {
return mz_os_rand(buf, size);
}
#endif

uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size) {
#if defined(HAVE_ZLIB)
return (uint32_t)ZLIB_PREFIX(crc32)((z_crc_t)value, buf, (uInt)size);
#elif defined(HAVE_LZMA)
return (uint32_t)lzma_crc32(buf, (size_t)size, (uint32_t)value);
#else
static uint32_t crc32_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
value = ~value;

while (size > 0) {
value = (value >> 8) ^ crc32_table[(value ^ *buf) & 0xFF];

buf += 1;
size -= 1;
}

return ~value;
#endif
}

#if defined(HAVE_WZAES)
int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *salt,
int32_t salt_length, int32_t iteration_count, uint8_t *key, int32_t key_length) {
void *hmac1 = NULL;
void *hmac2 = NULL;
void *hmac3 = NULL;
int32_t err = MZ_OK;
uint16_t i = 0;
uint16_t j = 0;
uint16_t k = 0;
uint16_t block_count = 0;
uint8_t uu[MZ_HASH_SHA1_SIZE];
uint8_t ux[MZ_HASH_SHA1_SIZE];

if (password == NULL || salt == NULL || key == NULL)
return MZ_PARAM_ERROR;

memset(key, 0, key_length);

mz_crypt_hmac_create(&hmac1);
mz_crypt_hmac_create(&hmac2);
mz_crypt_hmac_create(&hmac3);

mz_crypt_hmac_set_algorithm(hmac1, MZ_HASH_SHA1);
mz_crypt_hmac_set_algorithm(hmac2, MZ_HASH_SHA1);
mz_crypt_hmac_set_algorithm(hmac3, MZ_HASH_SHA1);

err = mz_crypt_hmac_init(hmac1, password, password_length);
if (err == MZ_OK)
err = mz_crypt_hmac_init(hmac2, password, password_length);
if (err == MZ_OK)
err = mz_crypt_hmac_update(hmac2, salt, salt_length);

block_count = 1 + ((uint16_t)key_length - 1) / MZ_HASH_SHA1_SIZE;

for (i = 0; (err == MZ_OK) && (i < block_count); i += 1) {
memset(ux, 0, sizeof(ux));

err = mz_crypt_hmac_copy(hmac2, hmac3);
if (err != MZ_OK)
break;

uu[0] = (uint8_t)((i + 1) >> 24);
uu[1] = (uint8_t)((i + 1) >> 16);
uu[2] = (uint8_t)((i + 1) >> 8);
uu[3] = (uint8_t)(i + 1);

for (j = 0, k = 4; j < iteration_count; j += 1) {
err = mz_crypt_hmac_update(hmac3, uu, k);
if (err == MZ_OK)
err = mz_crypt_hmac_end(hmac3, uu, sizeof(uu));
if (err != MZ_OK)
break;

for(k = 0; k < MZ_HASH_SHA1_SIZE; k += 1)
ux[k] ^= uu[k];

err = mz_crypt_hmac_copy(hmac1, hmac3);
if (err != MZ_OK)
break;
}

if (err != MZ_OK)
break;

j = 0;
k = i * MZ_HASH_SHA1_SIZE;

while (j < MZ_HASH_SHA1_SIZE && k < key_length)
key[k++] = ux[j++];
}

/* hmac3 uses the same provider as hmac2, so it must be deleted
before the context is destroyed. */
mz_crypt_hmac_delete(&hmac3);
mz_crypt_hmac_delete(&hmac1);
mz_crypt_hmac_delete(&hmac2);

return err;
}
#endif

/***************************************************************************/
@@ -0,0 +1,65 @@
/* mz_crypt.h -- Crypto/hash functions
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_CRYPT_H
#define MZ_CRYPT_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size);

int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *salt,
int32_t salt_length, int32_t iteration_count, uint8_t *key, int32_t key_length);

/***************************************************************************/

int32_t mz_crypt_rand(uint8_t *buf, int32_t size);

void mz_crypt_sha_reset(void *handle);
int32_t mz_crypt_sha_begin(void *handle);
int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size);
int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size);
void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm);
void* mz_crypt_sha_create(void **handle);
void mz_crypt_sha_delete(void **handle);

void mz_crypt_aes_reset(void *handle);
int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size);
int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size);
int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length);
int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length);
void mz_crypt_aes_set_mode(void *handle, int32_t mode);
void* mz_crypt_aes_create(void **handle);
void mz_crypt_aes_delete(void **handle);

void mz_crypt_hmac_reset(void *handle);
int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length);
int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size);
int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size);
int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle);
void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm);
void* mz_crypt_hmac_create(void **handle);
void mz_crypt_hmac_delete(void **handle);

int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size,
const char *cert_pwd, uint8_t **signature, int32_t *signature_size);
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -0,0 +1,354 @@
/* mz_os.c -- System functions
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
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_crypt.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_os.h"

#include <ctype.h> /* tolower */

/***************************************************************************/

int32_t mz_path_combine(char *path, const char *join, int32_t max_path) {
int32_t path_len = 0;

if (path == NULL || join == NULL || max_path == 0)
return MZ_PARAM_ERROR;

path_len = (int32_t)strlen(path);

if (path_len == 0) {
strncpy(path, join, max_path - 1);
path[max_path - 1] = 0;
} else {
mz_path_append_slash(path, max_path, MZ_PATH_SLASH_PLATFORM);
strncat(path, join, max_path - path_len);
}

return MZ_OK;
}

int32_t mz_path_append_slash(char *path, int32_t max_path, char slash) {
int32_t path_len = (int32_t)strlen(path);
if ((path_len + 2) >= max_path)
return MZ_BUF_ERROR;
if (path[path_len - 1] != '\\' && path[path_len - 1] != '/') {
path[path_len] = slash;
path[path_len + 1] = 0;
}
return MZ_OK;
}

int32_t mz_path_remove_slash(char *path) {
int32_t path_len = (int32_t)strlen(path);
while (path_len > 0) {
if (path[path_len - 1] == '\\' || path[path_len - 1] == '/')
path[path_len - 1] = 0;
else
break;

path_len -= 1;
}
return MZ_OK;
}

int32_t mz_path_has_slash(const char *path) {
int32_t path_len = (int32_t)strlen(path);
if (path[path_len - 1] != '\\' && path[path_len - 1] != '/')
return MZ_EXIST_ERROR;
return MZ_OK;
}

int32_t mz_path_convert_slashes(char *path, char slash) {
int32_t i = 0;

for (i = 0; i < (int32_t)strlen(path); i += 1) {
if (path[i] == '\\' || path[i] == '/')
path[i] = slash;
}
return MZ_OK;
}

int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case) {
while (*path != 0) {
switch (*wildcard) {
case '*':

if (*(wildcard + 1) == 0)
return MZ_OK;

while (*path != 0) {
if (mz_path_compare_wc(path, (wildcard + 1), ignore_case) == MZ_OK)
return MZ_OK;

path += 1;
}

return MZ_EXIST_ERROR;

default:
/* Ignore differences in path slashes on platforms */
if ((*path == '\\' && *wildcard == '/') || (*path == '/' && *wildcard == '\\'))
break;

if (ignore_case) {
if (tolower(*path) != tolower(*wildcard))
return MZ_EXIST_ERROR;
} else {
if (*path != *wildcard)
return MZ_EXIST_ERROR;
}

break;
}

path += 1;
wildcard += 1;
}

if ((*wildcard != 0) && (*wildcard != '*'))
return MZ_EXIST_ERROR;

return MZ_OK;
}

int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) {
const char *source = path;
const char *check = output;
char *target = output;


if (max_output <= 0)
return MZ_PARAM_ERROR;

while (*source != 0 && max_output > 1) {
check = source;
if ((*check == '\\') || (*check == '/'))
check += 1;

if ((source == path) || (target == output) || (check != source)) {
/* Skip double paths */
if ((*check == '\\') || (*check == '/')) {
source += 1;
continue;
}
if (*check == '.') {
check += 1;

/* Remove . if at end of string and not at the beginning */
if ((*check == 0) && (source != path && target != output)) {
/* Copy last slash */
*target = *source;
target += 1;
max_output -= 1;
source += (check - source);
continue;
}
/* Remove . if not at end of string */
else if ((*check == '\\') || (*check == '/')) {
source += (check - source);
/* Skip slash if at beginning of string */
if (target == output && *source != 0)
source += 1;
continue;
}
/* Go to parent directory .. */
else if (*check == '.') {
check += 1;
if ((*check == 0) || (*check == '\\' || *check == '/')) {
source += (check - source);

/* Search backwards for previous slash */
if (target != output) {
target -= 1;
do {
if ((*target == '\\') || (*target == '/'))
break;

target -= 1;
max_output += 1;
} while (target > output);
}

if ((target == output) && (*source != 0))
source += 1;
if ((*target == '\\' || *target == '/') && (*source == 0))
target += 1;

*target = 0;
continue;
}
}
}
}

*target = *source;

source += 1;
target += 1;
max_output -= 1;
}

*target = 0;

if (*path == 0)
return MZ_INTERNAL_ERROR;

return MZ_OK;
}

int32_t mz_path_remove_filename(char *path) {
char *path_ptr = NULL;

if (path == NULL)
return MZ_PARAM_ERROR;

path_ptr = path + strlen(path) - 1;

while (path_ptr > path) {
if ((*path_ptr == '/') || (*path_ptr == '\\')) {
*path_ptr = 0;
break;
}

path_ptr -= 1;
}

if (path_ptr == path)
*path_ptr = 0;

return MZ_OK;
}

int32_t mz_path_remove_extension(char *path) {
char *path_ptr = NULL;

if (path == NULL)
return MZ_PARAM_ERROR;

path_ptr = path + strlen(path) - 1;

while (path_ptr > path) {
if ((*path_ptr == '/') || (*path_ptr == '\\'))
break;
if (*path_ptr == '.') {
*path_ptr = 0;
break;
}

path_ptr -= 1;
}

if (path_ptr == path)
*path_ptr = 0;

return MZ_OK;
}

int32_t mz_path_get_filename(const char *path, const char **filename) {
const char *match = NULL;

if (path == NULL || filename == NULL)
return MZ_PARAM_ERROR;

*filename = NULL;

for (match = path; *match != 0; match += 1) {
if ((*match == '\\') || (*match == '/'))
*filename = match + 1;
}

if (*filename == NULL)
return MZ_EXIST_ERROR;

return MZ_OK;
}

int32_t mz_dir_make(const char *path) {
int32_t err = MZ_OK;
int16_t len = 0;
char *current_dir = NULL;
char *match = NULL;
char hold = 0;


len = (int16_t)strlen(path);
if (len <= 0)
return 0;

current_dir = (char *)MZ_ALLOC((uint16_t)len + 1);
if (current_dir == NULL)
return MZ_MEM_ERROR;

strcpy(current_dir, path);
mz_path_remove_slash(current_dir);

err = mz_os_make_dir(current_dir);
if (err != MZ_OK) {
match = current_dir + 1;
while (1) {
while (*match != 0 && *match != '\\' && *match != '/')
match += 1;
hold = *match;
*match = 0;

err = mz_os_make_dir(current_dir);
if (err != MZ_OK)
break;
if (hold == 0)
break;

*match = hold;
match += 1;
}
}

MZ_FREE(current_dir);
return err;
}

int32_t mz_file_get_crc(const char *path, uint32_t *result_crc) {
void *stream = NULL;
uint32_t crc32 = 0;
int32_t read = 0;
int32_t err = MZ_OK;
uint8_t buf[16384];

mz_stream_os_create(&stream);

err = mz_stream_os_open(stream, path, MZ_OPEN_MODE_READ);

if (err == MZ_OK) {
do {
read = mz_stream_os_read(stream, buf, sizeof(buf));

if (read < 0) {
err = read;
break;
}

crc32 = mz_crypt_crc32_update(crc32, buf, read);
} while ((err == MZ_OK) && (read > 0));

mz_stream_os_close(stream);
}

*result_crc = crc32;

mz_stream_os_delete(&stream);

return err;
}

/***************************************************************************/
@@ -0,0 +1,175 @@
/* mz_os.h -- System functions
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_OS_H
#define MZ_OS_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

#if defined(__APPLE__)
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_OSX_DARWIN)
#elif defined(__riscos__)
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_RISCOS)
#elif defined(_WIN32)
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_WINDOWS_NTFS)
#else
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_UNIX)
#endif

#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP)
# define MZ_VERSION_MADEBY_ZIP_VERSION (63)
#elif defined(HAVE_WZAES)
# define MZ_VERSION_MADEBY_ZIP_VERSION (51)
#elif defined(HAVE_BZIP2)
# define MZ_VERSION_MADEBY_ZIP_VERSION (46)
#else
# define MZ_VERSION_MADEBY_ZIP_VERSION (45)
#endif

#define MZ_VERSION_MADEBY ((MZ_VERSION_MADEBY_HOST_SYSTEM << 8) | \
(MZ_VERSION_MADEBY_ZIP_VERSION))

#define MZ_PATH_SLASH_UNIX ('/')
#if defined(_WIN32)
# define MZ_PATH_SLASH_PLATFORM ('\\')
#else
# define MZ_PATH_SLASH_PLATFORM (MZ_PATH_SLASH_UNIX)
#endif

/***************************************************************************/

#if defined(_WIN32)
struct dirent {
char d_name[256];
};
typedef void* DIR;
#else
#include <dirent.h>
#endif

/***************************************************************************/
/* Shared functions */

int32_t mz_path_combine(char *path, const char *join, int32_t max_path);
/* Combines two paths */

int32_t mz_path_append_slash(char *path, int32_t max_path, char slash);
/* Appends a path slash on to the end of the path */

int32_t mz_path_remove_slash(char *path);
/* Removes a path slash from the end of the path */

int32_t mz_path_has_slash(const char *path);
/* Returns whether or not the path ends with slash */

int32_t mz_path_convert_slashes(char *path, char slash);
/* Converts the slashes in a path */

int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case);
/* Compare two paths with wildcard */

int32_t mz_path_resolve(const char *path, char *target, int32_t max_target);
/* Resolves path */

int32_t mz_path_remove_filename(char *path);
/* Remove the filename from a path */

int32_t mz_path_remove_extension(char *path);
/* Remove the extension from a path */

int32_t mz_path_get_filename(const char *path, const char **filename);
/* Get the filename from a path */

int32_t mz_dir_make(const char *path);
/* Creates a directory recursively */

int32_t mz_file_get_crc(const char *path, uint32_t *result_crc);
/* Gets the crc32 hash of a file */

/***************************************************************************/
/* Platform specific functions */

wchar_t *mz_os_unicode_string_create(const char *string, int32_t encoding);
/* Create unicode string from a utf8 string */

void mz_os_unicode_string_delete(wchar_t **string);
/* Delete a unicode string that was created */

uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding);
/* Create a utf8 string from a string with another encoding */

void mz_os_utf8_string_delete(uint8_t **string);
/* Delete a utf8 string that was created */

int32_t mz_os_rand(uint8_t *buf, int32_t size);
/* Random number generator (not cryptographically secure) */

int32_t mz_os_rename(const char *source_path, const char *target_path);
/* Rename a file */

int32_t mz_os_unlink(const char *path);
/* Delete an existing file */

int32_t mz_os_file_exists(const char *path);
/* Check to see if a file exists */

int64_t mz_os_get_file_size(const char *path);
/* Gets the length of a file */

int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date);
/* Gets a file's modified, access, and creation dates if supported */

int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date);
/* Sets a file's modified, access, and creation dates if supported */

int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes);
/* Gets a file's attributes */

int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes);
/* Sets a file's attributes */

int32_t mz_os_make_dir(const char *path);
/* Recursively creates a directory */

DIR* mz_os_open_dir(const char *path);
/* Opens a directory for listing */
struct
dirent* mz_os_read_dir(DIR *dir);
/* Reads a directory listing entry */

int32_t mz_os_close_dir(DIR *dir);
/* Closes a directory that has been opened for listing */

int32_t mz_os_is_dir(const char *path);
/* Checks to see if path is a directory */

int32_t mz_os_is_symlink(const char *path);
/* Checks to see if path is a symbolic link */

int32_t mz_os_make_symlink(const char *path, const char *target_path);
/* Creates a symbolic link pointing to a target */

int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path);
/* Gets the target path for a symbolic link */

uint64_t mz_os_ms_time(void);
/* Gets the time in milliseconds */

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
@@ -0,0 +1,367 @@
/* mz_os_posix.c -- System functions for posix
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_os.h"

#include <stdio.h> /* rename */
#include <errno.h>
#if defined(HAVE_ICONV)
#include <iconv.h>
#endif

#include <sys/types.h>
#include <sys/stat.h>

#ifndef _WIN32
# include <utime.h>
# include <unistd.h>
#endif
#if defined(__APPLE__)
# include <mach/clock.h>
# include <mach/mach.h>
#endif

#if defined(HAVE_GETRANDOM)
# include <sys/random.h>
#endif
#if defined(HAVE_LIBBSD)
# include <sys/types.h>
# ifndef __u_char_defined
typedef unsigned char u_char;
# endif
# include <bsd/stdlib.h> /* arc4random_buf */
#endif

/***************************************************************************/

#if defined(HAVE_ICONV)
uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding) {
iconv_t cd;
const char *from_encoding = NULL;
size_t result = 0;
size_t string_length = 0;
size_t string_utf8_size = 0;
uint8_t *string_utf8 = NULL;
uint8_t *string_utf8_ptr = NULL;

if (string == NULL)
return NULL;

if (encoding == MZ_ENCODING_CODEPAGE_437)
from_encoding = "CP437";
else if (encoding == MZ_ENCODING_CODEPAGE_932)
from_encoding = "CP932";
else if (encoding == MZ_ENCODING_CODEPAGE_936)
from_encoding = "CP936";
else if (encoding == MZ_ENCODING_CODEPAGE_950)
from_encoding = "CP950";
else if (encoding == MZ_ENCODING_UTF8)
from_encoding = "UTF-8";
else
return NULL;

cd = iconv_open("UTF-8", from_encoding);
if (cd == (iconv_t)-1)
return NULL;

string_length = strlen(string);
string_utf8_size = string_length * 2;
string_utf8 = (uint8_t *)MZ_ALLOC((int32_t)(string_utf8_size + 1));
string_utf8_ptr = string_utf8;

if (string_utf8) {
memset(string_utf8, 0, string_utf8_size + 1);

result = iconv(cd, (char **)&string, &string_length,
(char **)&string_utf8_ptr, &string_utf8_size);
}

iconv_close(cd);

if (result == (size_t)-1) {
MZ_FREE(string_utf8);
string_utf8 = NULL;
}

return string_utf8;
}
#else
uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding) {
size_t string_length = 0;
uint8_t *string_copy = NULL;

string_length = strlen(string);
string_copy = (uint8_t *)MZ_ALLOC((int32_t)(string_length + 1));
strncpy((char *)string_copy, string, string_length);
string_copy[string_length] = 0;

return string_copy;
}
#endif

void mz_os_utf8_string_delete(uint8_t **string) {
if (string != NULL) {
MZ_FREE(*string);
*string = NULL;
}
}

/***************************************************************************/

#if defined(HAVE_ARC4RANDOM_BUF)
int32_t mz_os_rand(uint8_t *buf, int32_t size) {
if (size < 0)
return 0;
arc4random_buf(buf, (uint32_t)size);
return size;
}
#elif defined(HAVE_ARC4RANDOM)
int32_t mz_os_rand(uint8_t *buf, int32_t size) {
int32_t left = size;
for (; left > 2; left -= 3, buf += 3) {
uint32_t val = arc4random();

buf[0] = (val) & 0xFF;
buf[1] = (val >> 8) & 0xFF;
buf[2] = (val >> 16) & 0xFF;
}
for (; left > 0; left--, buf++) {
*buf = arc4random() & 0xFF;
}
return size - left;
}
#elif defined(HAVE_GETRANDOM)
int32_t mz_os_rand(uint8_t *buf, int32_t size) {
int32_t left = size;
int32_t written = 0;

while (left > 0) {
written = getrandom(buf, left, 0);
if (written < 0)
return MZ_INTERNAL_ERROR;

buf += written;
left -= written;
}
return size - left;
}
#else
int32_t mz_os_rand(uint8_t *buf, int32_t size) {
static unsigned calls = 0;
int32_t i = 0;

/* Ensure different random header each time */
if (++calls == 1) {
#define PI_SEED 3141592654UL
srand((unsigned)(time(NULL) ^ PI_SEED));
}

while (i < size)
buf[i++] = (rand() >> 7) & 0xff;

return size;
}
#endif

int32_t mz_os_rename(const char *source_path, const char *target_path) {
if (rename(source_path, target_path) == -1)
return MZ_EXIST_ERROR;

return MZ_OK;
}

int32_t mz_os_unlink(const char *path) {
if (unlink(path) == -1)
return MZ_EXIST_ERROR;

return MZ_OK;
}

int32_t mz_os_file_exists(const char *path) {
struct stat path_stat;

memset(&path_stat, 0, sizeof(path_stat));
if (stat(path, &path_stat) == 0)
return MZ_OK;
return MZ_EXIST_ERROR;
}

int64_t mz_os_get_file_size(const char *path) {
struct stat path_stat;

memset(&path_stat, 0, sizeof(path_stat));
if (stat(path, &path_stat) == 0) {
/* Stat returns size taken up by directory entry, so return 0 */
if (S_ISDIR(path_stat.st_mode))
return 0;

return path_stat.st_size;
}

return 0;
}

int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date) {
struct stat path_stat;
char *name = NULL;
size_t len = 0;
int32_t err = MZ_INTERNAL_ERROR;

memset(&path_stat, 0, sizeof(path_stat));

if (strcmp(path, "-") != 0) {
/* Not all systems allow stat'ing a file with / appended */
len = strlen(path);
name = (char *)malloc(len + 1);
strncpy(name, path, len + 1);
mz_path_remove_slash(name);

if (stat(name, &path_stat) == 0) {
if (modified_date != NULL)
*modified_date = path_stat.st_mtime;
if (accessed_date != NULL)
*accessed_date = path_stat.st_atime;
/* Creation date not supported */
if (creation_date != NULL)
*creation_date = 0;

err = MZ_OK;
}

free(name);
}

return err;
}

int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date) {
struct utimbuf ut;

ut.actime = accessed_date;
ut.modtime = modified_date;

/* Creation date not supported */
MZ_UNUSED(creation_date);

if (utime(path, &ut) != 0)
return MZ_INTERNAL_ERROR;

return MZ_OK;
}

int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes) {
struct stat path_stat;
int32_t err = MZ_OK;

memset(&path_stat, 0, sizeof(path_stat));
if (lstat(path, &path_stat) == -1)
err = MZ_INTERNAL_ERROR;
*attributes = path_stat.st_mode;
return err;
}

int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes) {
int32_t err = MZ_OK;

if (chmod(path, (mode_t)attributes) == -1)
err = MZ_INTERNAL_ERROR;

return err;
}

int32_t mz_os_make_dir(const char *path) {
int32_t err = 0;

err = mkdir(path, 0755);

if (err != 0 && errno != EEXIST)
return MZ_INTERNAL_ERROR;

return MZ_OK;
}

DIR* mz_os_open_dir(const char *path) {
return opendir(path);
}

struct dirent* mz_os_read_dir(DIR *dir) {
if (dir == NULL)
return NULL;
return readdir(dir);
}

int32_t mz_os_close_dir(DIR *dir) {
if (dir == NULL)
return MZ_PARAM_ERROR;
if (closedir(dir) == -1)
return MZ_INTERNAL_ERROR;
return MZ_OK;
}

int32_t mz_os_is_dir(const char *path) {
struct stat path_stat;

memset(&path_stat, 0, sizeof(path_stat));
stat(path, &path_stat);
if (S_ISDIR(path_stat.st_mode))
return MZ_OK;

return MZ_EXIST_ERROR;
}

int32_t mz_os_is_symlink(const char *path) {
struct stat path_stat;

memset(&path_stat, 0, sizeof(path_stat));
lstat(path, &path_stat);
if (S_ISLNK(path_stat.st_mode))
return MZ_OK;

return MZ_EXIST_ERROR;
}

int32_t mz_os_make_symlink(const char *path, const char *target_path) {
if (symlink(target_path, path) != 0)
return MZ_INTERNAL_ERROR;
return MZ_OK;
}

int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path) {
size_t length = 0;

length = (size_t)readlink(path, target_path, max_target_path - 1);
if (length == (size_t)-1)
return MZ_EXIST_ERROR;

target_path[length] = 0;
return MZ_OK;
}

uint64_t mz_os_ms_time(void) {
struct timespec ts;

#if defined(__APPLE__)
clock_serv_t cclock;
mach_timespec_t mts;

host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);

ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
#else
clock_gettime(CLOCK_MONOTONIC, &ts);
#endif

return ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000);
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -0,0 +1,132 @@
/* mz_strm.h -- Stream interface
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_H
#define MZ_STREAM_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

#define MZ_STREAM_PROP_TOTAL_IN (1)
#define MZ_STREAM_PROP_TOTAL_IN_MAX (2)
#define MZ_STREAM_PROP_TOTAL_OUT (3)
#define MZ_STREAM_PROP_TOTAL_OUT_MAX (4)
#define MZ_STREAM_PROP_HEADER_SIZE (5)
#define MZ_STREAM_PROP_FOOTER_SIZE (6)
#define MZ_STREAM_PROP_DISK_SIZE (7)
#define MZ_STREAM_PROP_DISK_NUMBER (8)
#define MZ_STREAM_PROP_COMPRESS_LEVEL (9)
#define MZ_STREAM_PROP_COMPRESS_METHOD (10)
#define MZ_STREAM_PROP_COMPRESS_WINDOW (11)

/***************************************************************************/

typedef int32_t (*mz_stream_open_cb) (void *stream, const char *path, int32_t mode);
typedef int32_t (*mz_stream_is_open_cb) (void *stream);
typedef int32_t (*mz_stream_read_cb) (void *stream, void *buf, int32_t size);
typedef int32_t (*mz_stream_write_cb) (void *stream, const void *buf, int32_t size);
typedef int64_t (*mz_stream_tell_cb) (void *stream);
typedef int32_t (*mz_stream_seek_cb) (void *stream, int64_t offset, int32_t origin);
typedef int32_t (*mz_stream_close_cb) (void *stream);
typedef int32_t (*mz_stream_error_cb) (void *stream);
typedef void* (*mz_stream_create_cb) (void **stream);
typedef void (*mz_stream_destroy_cb) (void **stream);

typedef int32_t (*mz_stream_get_prop_int64_cb) (void *stream, int32_t prop, int64_t *value);
typedef int32_t (*mz_stream_set_prop_int64_cb) (void *stream, int32_t prop, int64_t value);

typedef int32_t (*mz_stream_find_cb) (void *stream, const void *find, int32_t find_size,
int64_t max_seek, int64_t *position);

/***************************************************************************/

typedef struct mz_stream_vtbl_s {
mz_stream_open_cb open;
mz_stream_is_open_cb is_open;
mz_stream_read_cb read;
mz_stream_write_cb write;
mz_stream_tell_cb tell;
mz_stream_seek_cb seek;
mz_stream_close_cb close;
mz_stream_error_cb error;
mz_stream_create_cb create;
mz_stream_destroy_cb destroy;

mz_stream_get_prop_int64_cb get_prop_int64;
mz_stream_set_prop_int64_cb set_prop_int64;
} mz_stream_vtbl;

typedef struct mz_stream_s {
mz_stream_vtbl *vtbl;
struct mz_stream_s *base;
} mz_stream;

/***************************************************************************/

int32_t mz_stream_open(void *stream, const char *path, int32_t mode);
int32_t mz_stream_is_open(void *stream);
int32_t mz_stream_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_read_uint8(void *stream, uint8_t *value);
int32_t mz_stream_read_uint16(void *stream, uint16_t *value);
int32_t mz_stream_read_uint32(void *stream, uint32_t *value);
int32_t mz_stream_read_int64(void *stream, int64_t *value);
int32_t mz_stream_read_uint64(void *stream, uint64_t *value);
int32_t mz_stream_write(void *stream, const void *buf, int32_t size);
int32_t mz_stream_write_uint8(void *stream, uint8_t value);
int32_t mz_stream_write_uint16(void *stream, uint16_t value);
int32_t mz_stream_write_uint32(void *stream, uint32_t value);
int32_t mz_stream_write_int64(void *stream, int64_t value);
int32_t mz_stream_write_uint64(void *stream, uint64_t value);
int32_t mz_stream_copy(void *target, void *source, int32_t len);
int32_t mz_stream_copy_to_end(void *target, void *source);
int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb, int32_t len);
int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb);
int64_t mz_stream_tell(void *stream);
int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position);
int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position);
int32_t mz_stream_close(void *stream);
int32_t mz_stream_error(void *stream);

int32_t mz_stream_set_base(void *stream, void *base);
void* mz_stream_get_interface(void *stream);
int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value);

void* mz_stream_create(void **stream, mz_stream_vtbl *vtbl);
void mz_stream_delete(void **stream);

/***************************************************************************/

int32_t mz_stream_raw_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_raw_is_open(void *stream);
int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_raw_tell(void *stream);
int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_raw_close(void *stream);
int32_t mz_stream_raw_error(void *stream);

int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value);

void* mz_stream_raw_create(void **stream);
void mz_stream_raw_delete(void **stream);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif
@@ -0,0 +1,385 @@
/* mz_strm_buf.c -- Stream for buffering reads/writes
part of the minizip-ng project
This version of ioapi is designed to buffer IO.
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_buf.h"

/***************************************************************************/

static mz_stream_vtbl mz_stream_buffered_vtbl = {
mz_stream_buffered_open,
mz_stream_buffered_is_open,
mz_stream_buffered_read,
mz_stream_buffered_write,
mz_stream_buffered_tell,
mz_stream_buffered_seek,
mz_stream_buffered_close,
mz_stream_buffered_error,
mz_stream_buffered_create,
mz_stream_buffered_delete,
NULL,
NULL
};

/***************************************************************************/

typedef struct mz_stream_buffered_s {
mz_stream stream;
int32_t error;
char readbuf[INT16_MAX];
int32_t readbuf_len;
int32_t readbuf_pos;
int32_t readbuf_hits;
int32_t readbuf_misses;
char writebuf[INT16_MAX];
int32_t writebuf_len;
int32_t writebuf_pos;
int32_t writebuf_hits;
int32_t writebuf_misses;
int64_t position;
} mz_stream_buffered;

/***************************************************************************/

#if 0
# define mz_stream_buffered_print printf
#else
# define mz_stream_buffered_print(fmt,...)
#endif

/***************************************************************************/

static int32_t mz_stream_buffered_reset(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;

buffered->readbuf_len = 0;
buffered->readbuf_pos = 0;
buffered->writebuf_len = 0;
buffered->writebuf_pos = 0;
buffered->position = 0;

return MZ_OK;
}

int32_t mz_stream_buffered_open(void *stream, const char *path, int32_t mode) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
mz_stream_buffered_print("Buffered - Open (mode %" PRId32 ")\n", mode);
mz_stream_buffered_reset(buffered);
return mz_stream_open(buffered->stream.base, path, mode);
}

int32_t mz_stream_buffered_is_open(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
return mz_stream_is_open(buffered->stream.base);
}

static int32_t mz_stream_buffered_flush(void *stream, int32_t *written) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t total_bytes_written = 0;
int32_t bytes_to_write = buffered->writebuf_len;
int32_t bytes_left_to_write = buffered->writebuf_len;
int32_t bytes_written = 0;

*written = 0;

while (bytes_left_to_write > 0) {
bytes_written = mz_stream_write(buffered->stream.base,
buffered->writebuf + (bytes_to_write - bytes_left_to_write), bytes_left_to_write);

if (bytes_written != bytes_left_to_write)
return MZ_WRITE_ERROR;

buffered->writebuf_misses += 1;

mz_stream_buffered_print("Buffered - Write flush (%" PRId32 ":%" PRId32 " len %" PRId32 ")\n",
bytes_to_write, bytes_left_to_write, buffered->writebuf_len);

total_bytes_written += bytes_written;
bytes_left_to_write -= bytes_written;
buffered->position += bytes_written;
}

buffered->writebuf_len = 0;
buffered->writebuf_pos = 0;

*written = total_bytes_written;
return MZ_OK;
}

int32_t mz_stream_buffered_read(void *stream, void *buf, int32_t size) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t buf_len = 0;
int32_t bytes_to_read = 0;
int32_t bytes_to_copy = 0;
int32_t bytes_left_to_read = size;
int32_t bytes_read = 0;
int32_t bytes_flushed = 0;

mz_stream_buffered_print("Buffered - Read (size %" PRId32 " pos %" PRId64 ")\n", size, buffered->position);

if (buffered->writebuf_len > 0) {
int64_t position = buffered->position + buffered->writebuf_pos

mz_stream_buffered_print("Buffered - Switch from write to read, flushing (pos %" PRId64 ")\n", position);

mz_stream_buffered_flush(stream, &bytes_flushed);
mz_stream_buffered_seek(stream, position, MZ_SEEK_SET);
}

while (bytes_left_to_read > 0) {
if ((buffered->readbuf_len == 0) || (buffered->readbuf_pos == buffered->readbuf_len)) {
if (buffered->readbuf_len == sizeof(buffered->readbuf)) {
buffered->readbuf_pos = 0;
buffered->readbuf_len = 0;
}

bytes_to_read = (int32_t)sizeof(buffered->readbuf) - (buffered->readbuf_len - buffered->readbuf_pos);
bytes_read = mz_stream_read(buffered->stream.base, buffered->readbuf + buffered->readbuf_pos, bytes_to_read);
if (bytes_read < 0)
return bytes_read;

buffered->readbuf_misses += 1;
buffered->readbuf_len += bytes_read;
buffered->position += bytes_read;

mz_stream_buffered_print("Buffered - Filled (read %" PRId32 "/%" PRId32 " buf %" PRId32 ":%" PRId32 " pos %" PRId64 ")\n",
bytes_read, bytes_to_read, buffered->readbuf_pos, buffered->readbuf_len, buffered->position);

if (bytes_read == 0)
break;
}

if ((buffered->readbuf_len - buffered->readbuf_pos) > 0) {
bytes_to_copy = buffered->readbuf_len - buffered->readbuf_pos;
if (bytes_to_copy > bytes_left_to_read)
bytes_to_copy = bytes_left_to_read;

memcpy((char *)buf + buf_len, buffered->readbuf + buffered->readbuf_pos, bytes_to_copy);

buf_len += bytes_to_copy;
bytes_left_to_read -= bytes_to_copy;

buffered->readbuf_hits += 1;
buffered->readbuf_pos += bytes_to_copy;

mz_stream_buffered_print("Buffered - Emptied (copied %" PRId32 " remaining %" PRId32 " buf %" PRId32 ":%" PRId32 " pos %" PRId64 ")\n",
bytes_to_copy, bytes_left_to_read, buffered->readbuf_pos, buffered->readbuf_len, buffered->position);
}
}

return size - bytes_left_to_read;
}

int32_t mz_stream_buffered_write(void *stream, const void *buf, int32_t size) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t bytes_to_write = size;
int32_t bytes_left_to_write = size;
int32_t bytes_to_copy = 0;
int32_t bytes_used = 0;
int32_t bytes_flushed = 0;
int32_t err = MZ_OK;


mz_stream_buffered_print("Buffered - Write (size %" PRId32 " len %" PRId32 " pos %" PRId64 ")\n",
size, buffered->writebuf_len, buffered->position);

if (buffered->readbuf_len > 0) {
buffered->position -= buffered->readbuf_len;
buffered->position += buffered->readbuf_pos;

buffered->readbuf_len = 0;
buffered->readbuf_pos = 0;

mz_stream_buffered_print("Buffered - Switch from read to write (pos %" PRId64 ")\n", buffered->position);

err = mz_stream_seek(buffered->stream.base, buffered->position, MZ_SEEK_SET);
if (err != MZ_OK)
return err;
}

while (bytes_left_to_write > 0) {
bytes_used = buffered->writebuf_len;
if (bytes_used > buffered->writebuf_pos)
bytes_used = buffered->writebuf_pos;
bytes_to_copy = (int32_t)sizeof(buffered->writebuf) - bytes_used;
if (bytes_to_copy > bytes_left_to_write)
bytes_to_copy = bytes_left_to_write;

if (bytes_to_copy == 0) {
err = mz_stream_buffered_flush(stream, &bytes_flushed);
if (err != MZ_OK)
return err;
if (bytes_flushed == 0)
return 0;

continue;
}

memcpy(buffered->writebuf + buffered->writebuf_pos,
(const char *)buf + (bytes_to_write - bytes_left_to_write), bytes_to_copy);

mz_stream_buffered_print("Buffered - Write copy (remaining %" PRId32 " write %" PRId32 ":%" PRId32 " len %" PRId32 ")\n",
bytes_to_copy, bytes_to_write, bytes_left_to_write, buffered->writebuf_len);

bytes_left_to_write -= bytes_to_copy;

buffered->writebuf_pos += bytes_to_copy;
buffered->writebuf_hits += 1;
if (buffered->writebuf_pos > buffered->writebuf_len)
buffered->writebuf_len += buffered->writebuf_pos - buffered->writebuf_len;
}

return size - bytes_left_to_write;
}

int64_t mz_stream_buffered_tell(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int64_t position = mz_stream_tell(buffered->stream.base);

buffered->position = position;

mz_stream_buffered_print("Buffered - Tell (pos %" PRId64 " readpos %" PRId32 " writepos %" PRId32 ")\n",
buffered->position, buffered->readbuf_pos, buffered->writebuf_pos);

if (buffered->readbuf_len > 0)
position -= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos);
if (buffered->writebuf_len > 0)
position += buffered->writebuf_pos;
return position;
}

int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t bytes_flushed = 0;
int32_t err = MZ_OK;

mz_stream_buffered_print("Buffered - Seek (origin %" PRId32 " offset %" PRId64 " pos %" PRId64 ")\n",
origin, offset, buffered->position);

switch (origin) {
case MZ_SEEK_SET:

if ((buffered->readbuf_len > 0) && (offset < buffered->position) &&
(offset >= buffered->position - buffered->readbuf_len)) {
buffered->readbuf_pos = (int32_t)(offset - (buffered->position - buffered->readbuf_len));
return MZ_OK;
}
if (buffered->writebuf_len > 0) {
if ((offset >= buffered->position) && (offset <= buffered->position + buffered->writebuf_len)) {
buffered->writebuf_pos = (int32_t)(offset - buffered->position);
return MZ_OK;
}
}

err = mz_stream_buffered_flush(stream, &bytes_flushed);
if (err != MZ_OK)
return err;

buffered->position = offset;
break;

case MZ_SEEK_CUR:

if (buffered->readbuf_len > 0) {
if (offset <= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos)) {
buffered->readbuf_pos += (uint32_t)offset;
return MZ_OK;
}
offset -= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos);
buffered->position += offset;
}
if (buffered->writebuf_len > 0) {
if (offset <= ((int64_t)buffered->writebuf_len - buffered->writebuf_pos)) {
buffered->writebuf_pos += (uint32_t)offset;
return MZ_OK;
}
/* offset -= (buffered->writebuf_len - buffered->writebuf_pos); */
}

err = mz_stream_buffered_flush(stream, &bytes_flushed);
if (err != MZ_OK)
return err;

break;

case MZ_SEEK_END:

if (buffered->writebuf_len > 0) {
buffered->writebuf_pos = buffered->writebuf_len;
return MZ_OK;
}
break;
}

buffered->readbuf_len = 0;
buffered->readbuf_pos = 0;
buffered->writebuf_len = 0;
buffered->writebuf_pos = 0;

return mz_stream_seek(buffered->stream.base, offset, origin);
}

int32_t mz_stream_buffered_close(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t bytes_flushed = 0;

mz_stream_buffered_flush(stream, &bytes_flushed);
mz_stream_buffered_print("Buffered - Close (flushed %" PRId32 ")\n", bytes_flushed);

if (buffered->readbuf_hits + buffered->readbuf_misses > 0) {
mz_stream_buffered_print("Buffered - Read efficiency %.02f%%\n",
(buffered->readbuf_hits / ((float)buffered->readbuf_hits + buffered->readbuf_misses)) * 100);
}

if (buffered->writebuf_hits + buffered->writebuf_misses > 0) {
mz_stream_buffered_print("Buffered - Write efficiency %.02f%%\n",
(buffered->writebuf_hits / ((float)buffered->writebuf_hits + buffered->writebuf_misses)) * 100);
}

mz_stream_buffered_reset(buffered);

return mz_stream_close(buffered->stream.base);
}

int32_t mz_stream_buffered_error(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
return mz_stream_error(buffered->stream.base);
}

void *mz_stream_buffered_create(void **stream) {
mz_stream_buffered *buffered = NULL;

buffered = (mz_stream_buffered *)MZ_ALLOC(sizeof(mz_stream_buffered));
if (buffered != NULL) {
memset(buffered, 0, sizeof(mz_stream_buffered));
buffered->stream.vtbl = &mz_stream_buffered_vtbl;
}
if (stream != NULL)
*stream = buffered;

return buffered;
}

void mz_stream_buffered_delete(void **stream) {
mz_stream_buffered *buffered = NULL;
if (stream == NULL)
return;
buffered = (mz_stream_buffered *)*stream;
if (buffered != NULL)
MZ_FREE(buffered);
*stream = NULL;
}

void *mz_stream_buffered_get_interface(void) {
return (void *)&mz_stream_buffered_vtbl;
}
@@ -0,0 +1,42 @@
/* mz_strm_buf.h -- Stream for buffering reads/writes
part of the minizip-ng project
This version of ioapi is designed to buffer IO.
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_BUFFERED_H
#define MZ_STREAM_BUFFERED_H

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************/

int32_t mz_stream_buffered_open(void *stream, const char *path, int32_t mode);
int32_t mz_stream_buffered_is_open(void *stream);
int32_t mz_stream_buffered_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_buffered_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_buffered_tell(void *stream);
int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_buffered_close(void *stream);
int32_t mz_stream_buffered_error(void *stream);

void* mz_stream_buffered_create(void **stream);
void mz_stream_buffered_delete(void **stream);

void* mz_stream_buffered_get_interface(void);

/***************************************************************************/

#ifdef __cplusplus
}
#endif

#endif