#include "mz.h" #include "mz_strm.h" #include "mz_strm_mem.h" #include "ioapi.h" typedef struct mz_stream_ioapi_s { mz_stream stream; void *handle; zlib_filefunc_def filefunc; zlib_filefunc64_def filefunc64; } mz_stream_ioapi; /***************************************************************************/ static int32_t mz_stream_ioapi_open(void *stream, const char *path, int32_t mode); static int32_t mz_stream_ioapi_is_open(void *stream); static int32_t mz_stream_ioapi_read(void *stream, void *buf, int32_t size); static int32_t mz_stream_ioapi_write(void *stream, const void *buf, int32_t size); static int64_t mz_stream_ioapi_tell(void *stream); static int32_t mz_stream_ioapi_seek(void *stream, int64_t offset, int32_t origin); static int32_t mz_stream_ioapi_close(void *stream); static int32_t mz_stream_ioapi_error(void *stream); /***************************************************************************/ static mz_stream_vtbl mz_stream_ioapi_vtbl = {mz_stream_ioapi_open, mz_stream_ioapi_is_open, mz_stream_ioapi_read, mz_stream_ioapi_write, mz_stream_ioapi_tell, mz_stream_ioapi_seek, mz_stream_ioapi_close, mz_stream_ioapi_error, mz_stream_ioapi_create, mz_stream_ioapi_delete, NULL, NULL}; /***************************************************************************/ static int32_t mz_stream_ioapi_open(void *stream, const char *path, int32_t mode) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; int32_t ioapi_mode = 0; if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) ioapi_mode = ZLIB_FILEFUNC_MODE_READ; else if (mode & MZ_OPEN_MODE_APPEND) ioapi_mode = ZLIB_FILEFUNC_MODE_EXISTING; else if (mode & MZ_OPEN_MODE_CREATE) ioapi_mode = ZLIB_FILEFUNC_MODE_CREATE; else return MZ_OPEN_ERROR; if (ioapi->filefunc64.zopen64_file) ioapi->handle = ioapi->filefunc64.zopen64_file(ioapi->filefunc64.opaque, path, ioapi_mode); else if (ioapi->filefunc.zopen_file) ioapi->handle = ioapi->filefunc.zopen_file(ioapi->filefunc.opaque, path, ioapi_mode); if (!ioapi->handle) return MZ_PARAM_ERROR; return MZ_OK; } static int32_t mz_stream_ioapi_is_open(void *stream) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; if (!ioapi->handle) return MZ_OPEN_ERROR; return MZ_OK; } static int32_t mz_stream_ioapi_read(void *stream, void *buf, int32_t size) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; read_file_func zread = NULL; void *opaque = NULL; if (mz_stream_ioapi_is_open(stream) != MZ_OK) return MZ_OPEN_ERROR; if (ioapi->filefunc64.zread_file) { zread = ioapi->filefunc64.zread_file; opaque = ioapi->filefunc64.opaque; } else if (ioapi->filefunc.zread_file) { zread = ioapi->filefunc.zread_file; opaque = ioapi->filefunc.opaque; } else return MZ_PARAM_ERROR; return (int32_t)zread(opaque, ioapi->handle, buf, size); } static int32_t mz_stream_ioapi_write(void *stream, const void *buf, int32_t size) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; write_file_func zwrite = NULL; int32_t written = 0; void *opaque = NULL; if (mz_stream_ioapi_is_open(stream) != MZ_OK) return MZ_OPEN_ERROR; if (ioapi->filefunc64.zwrite_file) { zwrite = ioapi->filefunc64.zwrite_file; opaque = ioapi->filefunc64.opaque; } else if (ioapi->filefunc.zwrite_file) { zwrite = ioapi->filefunc.zwrite_file; opaque = ioapi->filefunc.opaque; } else return MZ_PARAM_ERROR; written = (int32_t)zwrite(opaque, ioapi->handle, buf, size); return written; } static int64_t mz_stream_ioapi_tell(void *stream) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; if (mz_stream_ioapi_is_open(stream) != MZ_OK) return MZ_OPEN_ERROR; if (ioapi->filefunc64.ztell64_file) return ioapi->filefunc64.ztell64_file(ioapi->filefunc64.opaque, ioapi->handle); else if (ioapi->filefunc.ztell_file) return ioapi->filefunc.ztell_file(ioapi->filefunc.opaque, ioapi->handle); return MZ_INTERNAL_ERROR; } static int32_t mz_stream_ioapi_seek(void *stream, int64_t offset, int32_t origin) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; if (mz_stream_ioapi_is_open(stream) != MZ_OK) return MZ_OPEN_ERROR; if (ioapi->filefunc64.zseek64_file) { if (ioapi->filefunc64.zseek64_file(ioapi->filefunc64.opaque, ioapi->handle, offset, origin) != 0) return MZ_INTERNAL_ERROR; } else if (ioapi->filefunc.zseek_file) { if (ioapi->filefunc.zseek_file(ioapi->filefunc.opaque, ioapi->handle, (int32_t)offset, origin) != 0) return MZ_INTERNAL_ERROR; } else return MZ_PARAM_ERROR; return MZ_OK; } static int32_t mz_stream_ioapi_close(void *stream) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; close_file_func zclose = NULL; void *opaque = NULL; if (mz_stream_ioapi_is_open(stream) != MZ_OK) return MZ_OPEN_ERROR; if (ioapi->filefunc.zclose_file) { zclose = ioapi->filefunc.zclose_file; opaque = ioapi->filefunc.opaque; } else if (ioapi->filefunc64.zclose_file) { zclose = ioapi->filefunc64.zclose_file; opaque = ioapi->filefunc64.opaque; } else return MZ_PARAM_ERROR; if (zclose(opaque, ioapi->handle) != 0) return MZ_CLOSE_ERROR; ioapi->handle = NULL; return MZ_OK; } static int32_t mz_stream_ioapi_error(void *stream) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; testerror_file_func zerror = NULL; void *opaque = NULL; if (mz_stream_ioapi_is_open(stream) != MZ_OK) return MZ_OPEN_ERROR; if (ioapi->filefunc.zerror_file) { zerror = ioapi->filefunc.zerror_file; opaque = ioapi->filefunc.opaque; } else if (ioapi->filefunc64.zerror_file) { zerror = ioapi->filefunc64.zerror_file; opaque = ioapi->filefunc64.opaque; } else return MZ_PARAM_ERROR; return zerror(opaque, ioapi->handle); } int32_t mz_stream_ioapi_set_filefunc(void *stream, zlib_filefunc_def *filefunc) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; memcpy(&ioapi->filefunc, filefunc, sizeof(zlib_filefunc_def)); return MZ_OK; } int32_t mz_stream_ioapi_set_filefunc64(void *stream, zlib_filefunc64_def *filefunc) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; memcpy(&ioapi->filefunc64, filefunc, sizeof(zlib_filefunc64_def)); return MZ_OK; } void *mz_stream_ioapi_create(void) { mz_stream_ioapi *ioapi = (mz_stream_ioapi *)calloc(1, sizeof(mz_stream_ioapi)); if (ioapi) ioapi->stream.vtbl = &mz_stream_ioapi_vtbl; return ioapi; } void mz_stream_ioapi_delete(void **stream) { mz_stream_ioapi *ioapi = NULL; if (!stream) return; ioapi = (mz_stream_ioapi *)*stream; free(ioapi); *stream = NULL; } /***************************************************************************/ void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def) { /* For 32-bit file support only, compile with MZ_FILE32_API */ if (pzlib_filefunc_def) memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc_def)); } void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def) { /* All mz_stream_os_* support large files if compilation supports it */ if (pzlib_filefunc_def) memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc64_def)); } void fill_win32_filefunc(zlib_filefunc_def *pzlib_filefunc_def) { /* Handled by mz_stream_os_win32 */ if (pzlib_filefunc_def) memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc_def)); } void fill_win32_filefunc64(zlib_filefunc64_def *pzlib_filefunc_def) { /* Automatically supported in mz_stream_os_win32 */ if (pzlib_filefunc_def) memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc64_def)); } void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def) { /* Automatically supported in mz_stream_os_win32 */ if (pzlib_filefunc_def) memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc64_def)); } /* NOTE: fill_win32_filefunc64W is no longer necessary since wide-character support is automatically handled by the underlying os stream. Do not pass wide-characters to zipOpen or unzOpen. */ void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def) { /* Use opaque to indicate which stream interface to create */ if (pzlib_filefunc_def) { memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc_def)); pzlib_filefunc_def->opaque = mz_stream_mem_get_interface(); } }