浏览代码

Merge pull request #3846 from assimp/issue_3831_update_zip

closes https://github.com/assimp/assimp/issues/3831 : update zip
Kim Kulling 4 年之前
父节点
当前提交
9ef84a67f7
共有 7 个文件被更改,包括 1053 次插入216 次删除
  1. 0 58
      contrib/zip/.gitignore
  2. 29 15
      contrib/zip/CMakeLists.txt
  3. 132 17
      contrib/zip/README.md
  4. 45 29
      contrib/zip/src/miniz.h
  5. 704 63
      contrib/zip/src/zip.c
  6. 109 27
      contrib/zip/src/zip.h
  7. 34 7
      contrib/zip/test/CMakeLists.txt

+ 0 - 58
contrib/zip/.gitignore

@@ -1,58 +0,0 @@
-/build/
-/test/build/
-/xcodeproj/
-.vscode/
-
-# Object files
-*.o
-*.ko
-*.obj
-*.elf
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Libraries
-*.lib
-*.a
-*.la
-*.lo
-
-# Shared objects (inc. Windows DLLs)
-*.dll
-*.so
-*.so.*
-*.dylib
-*.suo
-
-# Executables
-*.exe
-*.out
-*.app
-*.i*86
-*.x86_64
-*.hex
-
-# Temporary
-*.swp
-.DS_Store
-
-# CMake
-CMakeScripts
-*.cmake
-
-# Xcode
-*.build
-*.xcodeproj
-zip.sln
-zip.vcxproj.filters
-zip.vcxproj
-ALL_BUILD.vcxproj.filters
-ALL_BUILD.vcxproj
-CMakeFiles/
-zip.dir/
-test/test.exe.vcxproj.filters
-test/test.exe.vcxproj
-test/test.exe.dir/
-

+ 29 - 15
contrib/zip/CMakeLists.txt

@@ -1,26 +1,29 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.4)
 
 project(zip
   LANGUAGES C
-  VERSION "0.1.18")
+  VERSION "0.1.19")
 set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
-
+set(CMAKE_VERBOSE_MAKEFILE ON)
 option(CMAKE_DISABLE_TESTING "Disable test creation" OFF)
 
-if (MSVC)
-  # Use secure functions by default and suppress warnings about "deprecated" functions
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
-elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
-        "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
-        "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic")
-endif (MSVC)
-
 # zip
 set(SRC src/miniz.h src/zip.h src/zip.c)
-add_library(${PROJECT_NAME} ${SRC})
+
+# this is the "object library" target: compiles the sources only once
+add_library(OBJLIB OBJECT ${SRC})
+# shared libraries need PIC
+set_property(TARGET OBJLIB PROPERTY POSITION_INDEPENDENT_CODE 1)
+
+# static and shared libraries built from the same object files
+if (BUILD_SHARED_LIBS)
+  add_library(${PROJECT_NAME} SHARED $<TARGET_OBJECTS:OBJLIB>)
+  include(GenerateExportHeader)
+  generate_export_header(${PROJECT_NAME})
+else()
+  add_library(${PROJECT_NAME} STATIC $<TARGET_OBJECTS:OBJLIB>)
+endif()
+
 target_include_directories(${PROJECT_NAME} PUBLIC
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
   $<INSTALL_INTERFACE:include>
@@ -34,6 +37,17 @@ if (NOT CMAKE_DISABLE_TESTING)
   add_sanitizers(${PROJECT_NAME} ${test_out})
 endif()
 
+if (MSVC)
+  # Use secure functions by default and suppress warnings about "deprecated" functions
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
+elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
+        "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
+        "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -Werror -pedantic -Wno-deprecated")
+endif (MSVC)
+
 ####
 # Installation (https://github.com/forexample/package-example) {
 

+ 132 - 17
contrib/zip/README.md

@@ -2,7 +2,6 @@
 This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API.
 
 [![Build](https://github.com/kuba--/zip/workflows/build/badge.svg)](https://github.com/kuba--/zip/actions?query=workflow%3Abuild)
-[![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases)
 
 
 # The Idea
@@ -155,10 +154,52 @@ struct zip_t *zip = zip_open("foo.zip", 0, 'r');
 zip_close(zip);
 ```
 
+* Create a new zip archive in memory (stream API).
+
+```c
+char *outbuf = NULL;
+size_t outbufsize = 0;
+
+const char *inbuf = "Append some data here...\0";
+struct zip_t *zip = zip_stream_open(NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
+{
+    zip_entry_open(zip, "foo-1.txt");
+    {
+        zip_entry_write(zip, inbuf, strlen(inbuf));
+    }
+    zip_entry_close(zip);
+
+    /* copy compressed stream into outbuf */
+    zip_stream_copy(zip, (void **)&outbuf, &outbufsize);
+}
+zip_stream_close(zip);
+
+free(outbuf);
+```
+
+* Extract a zip entry into a memory (stream API).
+
+```c
+char *buf = NULL;
+ssize_t bufsize = 0;
+
+struct zip_t *zip = zip_stream_open(zipstream, zipstreamsize, 0, 'r');
+{
+    zip_entry_open(zip, "foo-1.txt");
+    {
+        zip_entry_read(zip, (void **)&buf, &bufsize);
+    }
+    zip_entry_close(zip);
+}
+zip_stream_close(zip);
+
+free(buf);
+```
+
 * List of all zip entries
 ```c
 struct zip_t *zip = zip_open("foo.zip", 0, 'r');
-int i, n = zip_total_entries(zip);
+int i, n = zip_entries_total(zip);
 for (i = 0; i < n; ++i) {
     zip_entry_openbyindex(zip, i);
     {
@@ -172,6 +213,49 @@ for (i = 0; i < n; ++i) {
 zip_close(zip);
 ```
 
+* Compress folder (recursively)
+```c
+void zip_walk(struct zip_t *zip, const char *path) {
+    DIR *dir;
+    struct dirent *entry;
+    char fullpath[MAX_PATH];
+    struct stat s;
+
+    memset(fullpath, 0, MAX_PATH);
+    dir = opendir(path);
+    assert(dir);
+
+    while ((entry = readdir(dir))) {
+      // skip "." and ".."
+      if (!strcmp(entry->d_name, ".\0") || !strcmp(entry->d_name, "..\0"))
+        continue;
+
+      snprintf(fullpath, sizeof(fullpath), "%s/%s", path, entry->d_name);
+      stat(fullpath, &s);
+      if (S_ISDIR(s.st_mode))
+        zip_walk(zip, fullpath);
+      else {
+        zip_entry_open(zip, fullpath);
+        zip_entry_fwrite(zip, fullpath);
+        zip_entry_close(zip);
+      }
+    }
+
+    closedir(dir);
+}
+```
+
+* Deletes zip archive entries.
+```c
+char *entries[] = {"unused.txt", "remove.ini", "delete.me"};
+
+struct zip_t *zip = zip_open("foo.zip", 0, 'd');
+{
+    zip_entries_delete(zip, entries, 3);
+}
+zip_close(zip);
+```
+
 # Bindings
 Compile zip library as a dynamic library.
 ```shell
@@ -181,7 +265,7 @@ $ cmake -DBUILD_SHARED_LIBS=true ..
 $ make
 ```
 
-### Go (cgo)
+### [Go](https://golang.org) (cgo)
 ```go
 package main
 
@@ -211,7 +295,7 @@ func main() {
 }
 ```
 
-### Rust (ffi)
+### [Rust](https://www.rust-lang.org) (ffi)
 ```rust
 extern crate libc;
 use std::ffi::CString;
@@ -236,7 +320,7 @@ extern "C" {
 }
 
 fn main() {
-    let path = CString::new("/tmp/test.zip").unwrap();
+    let path = CString::new("/tmp/rust.zip").unwrap();
     let mode: libc::c_char = 'w' as libc::c_char;
 
     let entryname = CString::new("test.txt").unwrap();
@@ -258,7 +342,7 @@ fn main() {
 }
 ```
 
-### Ruby (ffi)
+### [Ruby](http://www.ruby-lang.org) (ffi)
 Install _ffi_ gem.
 ```shell
 $ gem install ffi
@@ -291,7 +375,7 @@ Zip.zip_entry_close(ptr)
 Zip.zip_close(ptr)
 ```
 
-### Python (cffi)
+### [Python](https://www.python.org) (cffi)
 Install _cffi_ package
 ```shell
 $ pip install cffi
@@ -325,7 +409,36 @@ Zip.zip_entry_close(ptr)
 Zip.zip_close(ptr)
 ```
 
-### Ring
+### [Never](https://never-lang.readthedocs.io/) (ffi)
+```never
+extern "libzip.so" func zip_open(zipname: string, level: int, mode: char) -> c_ptr
+extern "libzip.so" func zip_close(zip: c_ptr) -> void
+
+extern "libzip.so" func zip_entry_open(zip: c_ptr, entryname: string) -> int
+extern "libzip.so" func zip_entry_close(zip: c_ptr) -> int
+extern "libzip.so" func zip_entry_write(zip: c_ptr, buf: string, bufsize: int) -> int
+extern "libzip.so" func zip_entry_fwrite(zip: c_ptr, filename: string) -> int
+
+func main() -> int
+{
+    let content = "Test content"
+
+    let zip = zip_open("/tmp/never.zip", 6, 'w');
+
+    zip_entry_open(zip, "test.file");
+    zip_entry_fwrite(zip, "/tmp/test.txt");
+    zip_entry_close(zip);
+
+    zip_entry_open(zip, "test.content");
+    zip_entry_write(zip, content, length(content));
+    zip_entry_close(zip);
+
+    zip_close(zip);
+    0
+}
+```
+
+### [Ring](http://ring-lang.net)
 The language comes with RingZip based on this library
 ```ring
 load "ziplib.ring"
@@ -342,13 +455,15 @@ new Zip {
 }
 ```
 
-# Contribution Rules/Coding Standards
-No need to throw away your coding style, just do your best to follow default clang-format style.
-Apply `clang-format` to the source files before commit:
-```sh
-for file in $(git ls-files | \grep -E '\.(c|h)$' | \grep -v -- '#')
-do
-    clang-format -i $file
-done
-```
+# Check out more cool projects which use this library:
+- [Filament](https://github.com/google/filament): Filament is a real-time physically based rendering engine for Android, iOS, Linux, macOS, Windows, and WebGL. It is designed to be as small as possible and as efficient as possible on Android.
+- [Hermes JS Engine](https://github.com/facebook/hermes): Hermes is a JavaScript engine optimized for fast start-up of React Native apps on Android. It features ahead-of-time static optimization and compact bytecode.
+- [Open Asset Import Library](https://github.com/assimp/assimp): A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
+- [PowerToys](https://github.com/microsoft/PowerToys): Set of utilities for power users to tune and streamline their Windows 10 experience for greater productivity.
+- [The Ring Programming Language](https://ring-lang.github.io): Innovative and practical general-purpose multi-paradigm language.
+- [The V Programming Language](https://github.com/vlang/v): Simple, fast, safe, compiled. For developing maintainable software.
+- [TIC-80](https://github.com/nesbox/TIC-80): TIC-80 is a FREE and OPEN SOURCE fantasy computer for making, playing and sharing tiny games.
+- [Urho3D](https://github.com/urho3d/Urho3D): Urho3D is a free lightweight, cross-platform 2D and 3D game engine implemented in C++ and released under the MIT license. Greatly inspired by OGRE and Horde3D.
+- [Vcpkg](https://github.com/microsoft/vcpkg): Vcpkg helps you manage C and C++ libraries on Windows, Linux and MacOS.
+- [and more...](https://grep.app/search?q=kuba--/zip)
 

+ 45 - 29
contrib/zip/src/miniz.h

@@ -400,7 +400,7 @@ typedef enum {
 #ifndef MINIZ_NO_ZLIB_APIS
 
 // Heap allocation callbacks.
-// Note that mz_alloc_func parameter types purpsosely differ from zlib's:
+// Note that mz_alloc_func parameter types purposely differ from zlib's:
 // items/size is size_t, not unsigned long.
 typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
 typedef void (*mz_free_func)(void *opaque, void *address);
@@ -2194,7 +2194,8 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r,
             } else
               tree_cur = pTable->m_tree[-tree_cur - 1];
           }
-          tree_cur -= ((rev_code >>= 1) & 1);
+          rev_code >>= 1;
+          tree_cur -= (rev_code & 1);
           pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
         }
         if (r->m_type == 2) {
@@ -3970,6 +3971,7 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
 
 #ifdef _MSC_VER
 #pragma warning(push)
+#pragma warning(disable : 4121 4127 4244)
 #pragma warning(disable : 4204) // nonstandard extension used : non-constant
                                 // aggregate initializer (also supported by GNU
                                 // C and C99, so no big deal)
@@ -4098,10 +4100,6 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
                                                     pLen_out, 6, MZ_FALSE);
 }
 
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
 // ------------------- .ZIP archive reading
 
 #ifndef MINIZ_NO_ARCHIVE_APIS
@@ -4112,18 +4110,39 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
 #include <stdio.h>
 #include <sys/stat.h>
 
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+
+#include <windows.h>
+
+static wchar_t *str2wstr(const char *str) {
+  int len = (int) strlen(str) + 1;
+  wchar_t *wstr = malloc(len * sizeof(wchar_t));
+  MultiByteToWideChar(CP_UTF8, 0, str, len * sizeof(char), wstr, len);
+  return wstr;
+}
+
 static FILE *mz_fopen(const char *pFilename, const char *pMode) {
-  FILE *pFile = NULL;
-  fopen_s(&pFile, pFilename, pMode);
+  wchar_t *wFilename = str2wstr(pFilename);
+  wchar_t *wMode = str2wstr(pMode);
+  FILE *pFile = _wfopen(wFilename, wMode);
+
+  free(wFilename);
+  free(wMode);
+
   return pFile;
 }
+
 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
-  FILE *pFile = NULL;
-  if (freopen_s(&pFile, pPath, pMode, pStream))
-    return NULL;
+  wchar_t *wPath = str2wstr(pPath);
+  wchar_t *wMode = str2wstr(pMode);
+  FILE *pFile = _wfreopen(wPath, wMode, pStream);
+
+  free(wPath);
+  free(wMode);
+
   return pFile;
 }
+
 #ifndef MINIZ_NO_TIME
 #include <sys/utime.h>
 #endif
@@ -4144,7 +4163,7 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
 #include <sys/utime.h>
 #endif
 #define MZ_FILE FILE
-#define MZ_FOPEN(f, m) fopen(f, m)
+#define MZ_FOPEN(f, m) mz_fopen
 #define MZ_FCLOSE fclose
 #define MZ_FREAD fread
 #define MZ_FWRITE fwrite
@@ -4153,7 +4172,7 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
 #define MZ_FILE_STAT_STRUCT _stat
 #define MZ_FILE_STAT _stat
 #define MZ_FFLUSH fflush
-#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
+#define MZ_FREOPEN(f, m, s) mz_freopen
 #define MZ_DELETE_FILE remove
 #elif defined(__TINYC__)
 #ifndef MINIZ_NO_TIME
@@ -5361,13 +5380,9 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
   } else {
     // Temporarily allocate a read buffer.
     read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
-#if defined(_MSC_VER) && !defined(__clang__)
-    if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
-        (read_buf_size > 0x7FFFFFFF))
-#else
     if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
-#endif
       return MZ_FALSE;
+
     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
                                             (size_t)read_buf_size)))
       return MZ_FALSE;
@@ -5454,11 +5469,7 @@ void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
   uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
 
   alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
-#if defined(_MSC_VER) && !defined(__clang__)
-  if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
-#else
   if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
-#endif
     return NULL;
   if (NULL ==
       (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
@@ -5560,14 +5571,10 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
     // The file is stored or the caller has requested the compressed data.
     if (pZip->m_pState->m_pMem) {
-#if defined (_MSC_VER) && !defined(__clang__)
-      if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
-          (file_stat.m_comp_size > 0xFFFFFFFF))
-#else
       if (((sizeof(size_t) == sizeof(mz_uint32))) &&
           (file_stat.m_comp_size > 0xFFFFFFFF))
-#endif
         return MZ_FALSE;
+
       if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
                     (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
         status = TINFL_STATUS_FAILED;
@@ -6085,7 +6092,7 @@ mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) {
   if (!pZip->m_file_offset_alignment)
     return 0;
   n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
-  return (mz_uint)(pZip->m_file_offset_alignment - n) &
+  return (pZip->m_file_offset_alignment - n) &
          (pZip->m_file_offset_alignment - 1);
 }
 
@@ -6289,7 +6296,10 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
                                mz_uint32 ext_attributes) {
   mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
   mz_uint16 method = 0, dos_time = 0, dos_date = 0;
+#ifndef MINIZ_NO_TIME
   time_t file_modified_time;
+#endif
+
   mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0,
                                                         comp_size = 0;
   size_t archive_name_size;
@@ -6326,10 +6336,12 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
         comment_size + archive_name_size) > 0xFFFFFFFF))
     return MZ_FALSE;
 
+#ifndef MINIZ_NO_TIME
   memset(&file_modified_time, 0, sizeof(file_modified_time));
   if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
     return MZ_FALSE;
   mz_zip_time_t_to_dos_time(file_modified_time, &dos_time, &dos_date);
+#endif
 
   pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
   if (!pSrc_file)
@@ -6814,6 +6826,10 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
   return p;
 }
 
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
 #endif // #ifndef MINIZ_NO_STDIO
 
 #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS

文件差异内容过多而无法显示
+ 704 - 63
contrib/zip/src/zip.c


+ 109 - 27
contrib/zip/src/zip.h

@@ -15,19 +15,11 @@
 #include <string.h>
 #include <sys/types.h>
 
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4127 )
-#endif //_MSC_VER
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) &&               \
-    !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) &&              \
-    !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(_SSIZE_T_DECLARED)
-
+#if !defined(_POSIX_C_SOURCE) && defined(_MSC_VER)
 // 64-bit Windows is the only mainstream platform
 // where sizeof(long) != sizeof(void*)
 #ifdef _WIN64
@@ -35,15 +27,6 @@ typedef long long ssize_t; /* byte count or error */
 #else
 typedef long ssize_t; /* byte count or error */
 #endif
-
-#define _SSIZE_T_DEFINED
-#define _SSIZE_T_DEFINED_
-#define __DEFINED_ssize_t
-#define __ssize_t_defined
-#define _SSIZE_T
-#define _SSIZE_T_
-#define _SSIZE_T_DECLARED
-
 #endif
 
 #ifndef MAX_PATH
@@ -64,9 +47,49 @@ typedef long ssize_t; /* byte count or error */
 /**
  * Default zip compression level.
  */
-
 #define ZIP_DEFAULT_COMPRESSION_LEVEL 6
 
+/**
+ * Error codes
+ */
+#define ZIP_ENOINIT -1      // not initialized
+#define ZIP_EINVENTNAME -2  // invalid entry name
+#define ZIP_ENOENT -3       // entry not found
+#define ZIP_EINVMODE -4     // invalid zip mode
+#define ZIP_EINVLVL -5      // invalid compression level
+#define ZIP_ENOSUP64 -6     // no zip 64 support
+#define ZIP_EMEMSET -7      // memset error
+#define ZIP_EWRTENT -8      // cannot write data to entry
+#define ZIP_ETDEFLINIT -9   // cannot initialize tdefl compressor
+#define ZIP_EINVIDX -10     // invalid index
+#define ZIP_ENOHDR -11      // header not found
+#define ZIP_ETDEFLBUF -12   // cannot flush tdefl buffer
+#define ZIP_ECRTHDR -13     // cannot create entry header
+#define ZIP_EWRTHDR -14     // cannot write entry header
+#define ZIP_EWRTDIR -15     // cannot write to central dir
+#define ZIP_EOPNFILE -16    // cannot open file
+#define ZIP_EINVENTTYPE -17 // invalid entry type
+#define ZIP_EMEMNOALLOC -18 // extracting data using no memory allocation
+#define ZIP_ENOFILE -19     // file not found
+#define ZIP_ENOPERM -20     // no permission
+#define ZIP_EOOMEM -21      // out of memory
+#define ZIP_EINVZIPNAME -22 // invalid zip archive name
+#define ZIP_EMKDIR -23      // make dir error
+#define ZIP_ESYMLINK -24    // symlink error
+#define ZIP_ECLSZIP -25     // close archive error
+#define ZIP_ECAPSIZE -26    // capacity size too small
+#define ZIP_EFSEEK -27      // fseek error
+#define ZIP_EFREAD -28      // fread error
+#define ZIP_EFWRITE -29     // fwrite error
+
+/**
+ * Looks up the error message string coresponding to an error number.
+ * @param errnum error number
+ * @return error message string coresponding to errnum or NULL if error is not
+ * found.
+ */
+extern const char *zip_strerror(int errnum);
+
 /**
  * @struct zip_t
  *
@@ -242,8 +265,8 @@ extern ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize);
  *
  * @note ensure supplied output buffer is large enough.
  *       zip_entry_size function (returns uncompressed size for the current
- *       entry) can be handy to estimate how big buffer is needed. for large
- * entries, please take a look at zip_entry_extract function.
+ *       entry) can be handy to estimate how big buffer is needed.
+ *       For large entries, please take a look at zip_entry_extract function.
  *
  * @return the return code - the number of bytes actually read on success.
  *         Otherwise a -1 on error (e.g. bufsize is not large enough).
@@ -285,7 +308,71 @@ zip_entry_extract(struct zip_t *zip,
  * @return the return code - the number of entries on success, negative number
  *         (< 0) on error.
  */
-extern int zip_total_entries(struct zip_t *zip);
+extern int zip_entries_total(struct zip_t *zip);
+
+/**
+ * Deletes zip archive entries.
+ *
+ * @param zip zip archive handler.
+ * @param entries array of zip archive entries to be deleted.
+ * @param len the number of entries to be deleted.
+ * @return the number of deleted entries, or negative number (< 0) on error.
+ */
+extern int zip_entries_delete(struct zip_t *zip, char *const entries[],
+                              size_t len);
+
+/**
+ * Extracts a zip archive stream into directory.
+ *
+ * If on_extract is not NULL, the callback will be called after
+ * successfully extracted each zip entry.
+ * Returning a negative value from the callback will cause abort and return an
+ * error. The last argument (void *arg) is optional, which you can use to pass
+ * data to the on_extract callback.
+ *
+ * @param stream zip archive stream.
+ * @param size stream size.
+ * @param dir output directory.
+ * @param on_extract on extract callback.
+ * @param arg opaque pointer.
+ *
+ * @return the return code - 0 on success, negative number (< 0) on error.
+ */
+extern int zip_stream_extract(const char *stream, size_t size, const char *dir,
+                              int (*on_extract)(const char *filename,
+                                                void *arg),
+                              void *arg);
+
+/**
+ * Opens zip archive stream into memory.
+ *
+ * @param stream zip archive stream.
+ * @param size stream size.
+ *
+ * @return the zip archive handler or NULL on error
+ */
+extern struct zip_t *zip_stream_open(const char *stream, size_t size, int level,
+                                     char mode);
+
+/**
+ * Copy zip archive stream output buffer.
+ *
+ * @param zip zip archive handler.
+ * @param buf output buffer. User should free buf.
+ * @param bufsize output buffer size (in bytes).
+ *
+ * @return copy size
+ */
+extern ssize_t zip_stream_copy(struct zip_t *zip, void **buf, ssize_t *bufsize);
+
+/**
+ * Close zip archive releases resources.
+ *
+ * @param zip zip archive handler.
+ *
+ * @return
+ */
+extern void zip_stream_close(struct zip_t *zip);
 
 /**
  * Creates a new archive and puts files into a single zip archive.
@@ -319,11 +406,6 @@ extern int zip_extract(const char *zipname, const char *dir,
                        void *arg);
 
 /** @} */
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif //_MSC_VER
-
 #ifdef __cplusplus
 }
 #endif

+ 34 - 7
contrib/zip/test/CMakeLists.txt

@@ -1,11 +1,38 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.4)
 
-# test
-set(test_out test.out)
+# tests
+set(test_write_out test_write.out)
+add_executable(${test_write_out} test_write.c)
+target_link_libraries(${test_write_out} zip)
+add_test(NAME ${test_write_out} COMMAND ${test_write_out})
+set(test_write_out ${test_write_out} PARENT_SCOPE)
 
-add_executable(${test_out} test.c)
-target_link_libraries(${test_out} zip)
+set(test_append_out test_append.out)
+add_executable(${test_append_out} test_append.c)
+target_link_libraries(${test_append_out} zip)
+add_test(NAME ${test_append_out} COMMAND ${test_append_out})
+set(test_append_out ${test_append_out} PARENT_SCOPE)
 
-add_test(NAME ${test_out} COMMAND ${test_out})
+set(test_read_out test_read.out)
+add_executable(${test_read_out} test_read.c)
+target_link_libraries(${test_read_out} zip)
+add_test(NAME ${test_read_out} COMMAND ${test_read_out})
+set(test_read_out ${test_read_out} PARENT_SCOPE)
 
-set(test_out ${test_out} PARENT_SCOPE)
+set(test_extract_out test_extract.out)
+add_executable(${test_extract_out} test_extract.c)
+target_link_libraries(${test_extract_out} zip)
+add_test(NAME ${test_extract_out} COMMAND ${test_extract_out})
+set(test_extract_out ${test_extract_out} PARENT_SCOPE)
+
+set(test_entry_out test_entry.out)
+add_executable(${test_entry_out} test_entry.c)
+target_link_libraries(${test_entry_out} zip)
+add_test(NAME ${test_entry_out} COMMAND ${test_entry_out})
+set(test_entry_out ${test_entry_out} PARENT_SCOPE)
+
+set(test_permissions_out test_permissions.out)
+add_executable(${test_permissions_out} test_permissions.c)
+target_link_libraries(${test_permissions_out} zip)
+add_test(NAME ${test_permissions_out} COMMAND ${test_permissions_out})
+set(test_permissions_out ${test_permissions_out} PARENT_SCOPE)

部分文件因为文件数量过多而无法显示