Repository: modelon-community/fmi-library
Pull request #169: CMake: System minizip option
Author: login: jschueller
Created: 2025-04-22T18:44:22Z | Merged: 2025-05-13T15:41:21Z

Similar to #134 
I also added a global option FMILIB_EXTERNAL_LIBS to close #100 

/cc @modelonrobinandersson @uilianries 

Linked issue #100: CMake option to not use bundled thirdparty
We are working on a so-called conan recipe to build fmi-library on conan center index (CCI), so that it can be made available via [conan](https://conan.io/) (a C / C++ package manager). 

The recipe will be maintained by the open source community. A good practice on CCI is to let conan handle the third-party dependencies instead of building third-party code. Currently (for 2.4.1), this necessitates several patches to workaround the external project compilation, see https://github.com/conan-io/conan-center-index/pull/20256, https://github.com/joakimono/conan-center-index/tree/fmilibrary/new-package/recipes/fmilib/all/patches.

It would be more maintainable if fmi-library could optionally disable bundled third-party dependencies, e.g. through a CMake option variable.

Could you please consider such feature on your next major release?

Linked issue comments: user: login: modelonrobinandersson
created_at: 2023-11-21T12:42:20Z
body: Hi @joakimono, thank you for the request. It sounds like a good idea and I'll see what we can do about this.
author_association: CONTRIBUTOR
user: login: jschueller
created_at: 2025-05-04T19:01:41Z
body: I also added a new option to use all system libraries
author_association: CONTRIBUTOR

Diff:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b1690344b..3e8dc8d99 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -27,6 +27,14 @@ jobs:
           cmake -DFMIL_HOME=~/.local -B build_test_install -LAH Test/test_installation/
           cmake --build build_test_install --target all
           ctest --test-dir build_test_install --output-on-failure
+      - name: Install third-party libs
+        run: sudo apt-get -y install libminizip-dev libexpat1-dev
+      - name: Build external
+        run: |
+          cmake -DCMAKE_INSTALL_PREFIX=~/.local -DFMILIB_GENERATE_DOXYGEN_DOC=0 -DFMILIB_EXTERNAL_LIBS=ON -DFMILIB_BUILD_STATIC_LIB=OFF -B build_external .
+          cmake --build build_external --target install --parallel 4
+      - name: Test external
+        run: ctest --test-dir build_external --output-on-failure
 
   windows:
     runs-on: windows-latest
@@ -42,7 +50,7 @@ jobs:
       - name: Build VS
         run: |
           cmake -DCMAKE_INSTALL_PREFIX="$($HOME -replace '\\', '/')/fmilib_install_vs" -DFMILIB_GENERATE_DOXYGEN_DOC=0 -DFMILIB_BUILD_TESTS=OFF -B build_vs -LAH . &&
-          cmake --build build_vs --target install --parallel 4
+          cmake --build build_vs --target install --config Release --parallel 4
       - name: Test Installation
         run: |
           cmake -DFMIL_HOME="$($HOME -replace '\\', '/')/fmilib_install_vs" -B build_test_install_vs -LAH Test/test_installation/ &&
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 527b1ea1a..9b5e72e68 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,9 +48,18 @@ endif()
 option(FMILIB_BUILD_STATIC_LIB "Build the library as static." ON)
 option(FMILIB_BUILD_SHARED_LIB "Build the library as shared (dll/so/dylib)." ON)
 option(FMILIB_INSTALL_SUBLIBS  "Install sub-libraries (fmicapi. fmixml, jmutil, fmiimport, fmizip)" OFF)
-option(FMILIB_FIND_PACKAGE_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_ZLIB "Use find_package for zlib, instead of version in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle zlib." OFF)
+if(DEFINED FMILIB_FIND_PACKAGE_ZLIB)
+    message(SEND_ERROR "FMILIB_FIND_PACKAGE_ZLIB is obsolete, use FMILIB_SYSTEM_ZLIB")
+endif()
+option(FMILIB_SYSTEM_MINIZIP "Use system minizip library instead of the one in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle minizip." OFF)
 option(FMILIB_SYSTEM_EXPAT "Use system expat library instead of the one in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle expat." OFF)
-mark_as_advanced(FMILIB_FIND_PACKAGE_ZLIB)
+option(FMILIB_EXTERNAL_LIBS "Use system libraries for all dependencies instead of the ones in FMILibrary/Thirdparty" OFF)
+if(FMILIB_EXTERNAL_LIBS)
+    set(FMILIB_SYSTEM_ZLIB ON CACHE BOOL "Use system zlib library" FORCE)
+    set(FMILIB_SYSTEM_MINIZIP ON CACHE BOOL "Use system minizp library" FORCE)
+    set(FMILIB_SYSTEM_EXPAT ON CACHE BOOL "Use system expat library" FORCE)
+endif()
 
 if(NOT (WIN32 OR CYGWIN OR APPLE))
 # On LINUX position independent code (-fPIC) must be used on all files to be linked into .so
@@ -278,7 +287,13 @@ if(FMILIB_BUILD_TESTS)
     )
 endif()
 
-set(FMILIB_SHARED_SUBLIBS fmixml fmizip fmicapi minizip zlib)
+set(FMILIB_SHARED_SUBLIBS fmixml fmizip fmicapi)
+if(NOT FMILIB_SYSTEM_MINIZIP)
+    list(APPEND FMILIB_SHARED_SUBLIBS minizip)
+endif()
+if(NOT FMILIB_SYSTEM_ZLIB)
+    list(APPEND FMILIB_SHARED_SUBLIBS zlib)
+endif()
 if(NOT FMILIB_SYSTEM_EXPAT)
     list(APPEND FMILIB_SHARED_SUBLIBS expat)
 endif()
diff --git a/Config.cmake/FindMiniZip.cmake b/Config.cmake/FindMiniZip.cmake
new file mode 100644
index 000000000..304c4078c
--- /dev/null
+++ b/Config.cmake/FindMiniZip.cmake
@@ -0,0 +1,17 @@
+# Find the Minizip library
+# Defines:
+
+#  MINIZIP_INCLUDE_DIR - minizip include directory
+#  MINIZIP_LIBRARY     - minizip library file
+#  MINIZIP_FOUND       - TRUE if minizip is found
+
+find_path(MINIZIP_INCLUDE_DIR NAMES unzip.h PATH_SUFFIXES minizip)
+
+if(MINIZIP_USE_STATIC_LIBS)
+  find_library(MINIZIP_LIBRARY NAMES ${CMAKE_STATIC_LIBRARY_PREFIX}minizip${CMAKE_STATIC_LIBRARY_SUFFIX} minizip)
+else()
+  find_library(MINIZIP_LIBRARY NAMES minizip)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(MiniZip DEFAULT_MSG MINIZIP_LIBRARY MINIZIP_INCLUDE_DIR)
diff --git a/Config.cmake/Minizip/CMakeLists.txt b/Config.cmake/Minizip/CMakeLists.txt
index 5fc93fc12..3f2c71677 100644
--- a/Config.cmake/Minizip/CMakeLists.txt
+++ b/Config.cmake/Minizip/CMakeLists.txt
@@ -31,8 +31,6 @@ endif()
 
 set(SOURCE
     ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/ioapi.c
-    ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/miniunz.c
-    ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/minizip.c
     #${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/mztools.c
     ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/unzip.c
     ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/zip.c
@@ -45,7 +43,6 @@ endif(WIN32)
 set(HEADERS
     ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/crypt.h
     ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/ioapi.h
-    ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/miniunz.h
     #${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/mztools.h
     ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip/unzip.h
 )
@@ -56,7 +53,7 @@ endif(WIN32)
 
 add_library(minizip ${SOURCE} ${HEADERS})
 
-target_link_libraries(minizip PRIVATE zlib)
+target_link_libraries(minizip PUBLIC zlib)
 
 target_include_directories(minizip
     PRIVATE ${ZLIB_INCLUDE_DIRS}
diff --git a/Config.cmake/fmizip.cmake b/Config.cmake/fmizip.cmake
index dc83c99a7..1a66c1d8d 100644
--- a/Config.cmake/fmizip.cmake
+++ b/Config.cmake/fmizip.cmake
@@ -18,11 +18,21 @@ include(jmutil)
 
 # set(DOXYFILE_EXTRA_SOURCES "${DOXYFILE_EXTRA_SOURCES} \"${FMIZIPDIR}/include\"")
 
-add_subdirectory(Config.cmake/Minizip)
+if(FMILIB_SYSTEM_MINIZIP)
+    find_package(MiniZip REQUIRED)
+    add_library(minizip UNKNOWN IMPORTED)
+    target_link_libraries(minizip INTERFACE ${MINIZIP_LIBRARY})
+    target_include_directories(minizip INTERFACE ${MINIZIP_INCLUDE_DIR})
+    set_target_properties(minizip PROPERTIES IMPORTED_LOCATION ${MINIZIP_LIBRARY})
+else ()
+    add_subdirectory(Config.cmake/Minizip)
+endif ()
 
 set(FMIZIPSOURCE
     ${FMIZIPDIR}/src/fmi_zip_unzip.c
     ${FMIZIPDIR}/src/fmi_zip_zip.c
+    ${FMIZIPDIR}/src/fmi_miniunz.c
+    ${FMIZIPDIR}/src/fmi_minizip.c
 )
 
 set(FMIZIPHEADERS
@@ -37,11 +47,17 @@ target_link_libraries(fmizip
 )
 target_include_directories(fmizip
     PRIVATE
-        ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip
+        ${ZLIB_INCLUDE_DIRS}
         ${FMILIB_THIRDPARTYLIBS}/FMI
     PUBLIC
         ${FMILIB_CONFIG_INCLUDE_DIR}
         ${FMIZIPDIR}/include
 )
 
+if(FMILIB_SYSTEM_MINIZIP AND TARGET zlib)
+    target_link_libraries(fmizip PRIVATE zlib)
+else()
+    target_include_directories(fmizip PRIVATE ${FMILIB_THIRDPARTYLIBS}/Minizip/minizip)
+endif()
+
 endif(NOT FMIZIPDIR)
diff --git a/Config.cmake/fmizlib.cmake b/Config.cmake/fmizlib.cmake
index f94928290..8b8123565 100644
--- a/Config.cmake/fmizlib.cmake
+++ b/Config.cmake/fmizlib.cmake
@@ -11,9 +11,8 @@
 #    You should have received a copy of the FMILIB_License.txt file
 #    along with this program. If not, contact Modelon AB <http://www.modelon.com>.
 
-if(FMILIB_FIND_PACKAGE_ZLIB)
+if(FMILIB_SYSTEM_ZLIB)
 
-    set(ZLIB_USE_STATIC_LIBS ON)
     include(FindZLIB)
 
     find_package(ZLIB)
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index f59b0a777..fab27e829 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -6,6 +6,8 @@ Note that version 2.1 is the first version with release notes. Please see the co
 
 ## FUTURE
 
+- Add FMILIB_EXTERNAL_LIBS option to enable external zlib/minizip/expat dependencies
+- CMake option FMILIB_FIND_PACKAGE_ZLIB is now obsolete, use FMILIB_SYSTEM_ZLIB instead
 - Use `c99_snprintf` third-party dependency only when compiling with MSVC 2015 and lower
 - Bump minimum cmake version 3.15 and enable compatibility with 4.x.
 
diff --git a/ThirdParty/Minizip/README.txt b/ThirdParty/Minizip/README.txt
index eaa812dbf..963f0d553 100644
--- a/ThirdParty/Minizip/README.txt
+++ b/ThirdParty/Minizip/README.txt
@@ -1,7 +1,5 @@
 The sources for minizip are copied from: https://github.com/madler/zlib/releases/tag/v1.3.1
 
-Additionally, a few changes have been made:
-1. Added the miniunz.h/minizip.h headers
-2. The main method in minizip.c has been renamed to minizip.
-3. The main method in miniunz.c as been renamed to miniunz.
-4. Use a dummy minizip_printf instead of printf
+Additionally:
+1. miniunz.c and minizip.c has been copied to fmi-library/src/ZIP/src/{fmi_miniunz.c,fmi_minizip.c}
+2. The above mentioned copied files have also been altered. See the file-level comment in each file for details.
\ No newline at end of file
diff --git a/ThirdParty/Minizip/minizip/miniunz.h b/ThirdParty/Minizip/minizip/miniunz.h
deleted file mode 100644
index d36973131..000000000
--- a/ThirdParty/Minizip/minizip/miniunz.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef MINIUNZ_H
-#define MINIUNZ_H
-#ifdef __cplusplus 
-extern "C" {
-#endif
-
-int miniunz(int argc , char *argv[]); /* Renamed the main function */
-#ifdef __cplusplus 
-}
-#endif
-#endif /* End of header file MINIUNZ_H */
\ No newline at end of file
diff --git a/ThirdParty/Minizip/minizip/minizip.h b/ThirdParty/Minizip/minizip/minizip.h
deleted file mode 100644
index ffead308a..000000000
--- a/ThirdParty/Minizip/minizip/minizip.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef MINIZIP_H
-#define MINIZIP_H
-#ifdef __cplusplus 
-extern "C" {
-#endif
-
-int minizip(int argc , char *argv[]); /* Renamed the main function */
-
-#ifdef __cplusplus 
-}
-#endif
-#endif /* End of header file MINIZIP_H */
\ No newline at end of file
diff --git a/src/ZIP/include/FMI/fmi_miniunz.h b/src/ZIP/include/FMI/fmi_miniunz.h
new file mode 100644
index 000000000..869ae786c
--- /dev/null
+++ b/src/ZIP/include/FMI/fmi_miniunz.h
@@ -0,0 +1,13 @@
+#ifndef FMI_MINIUNZ_H
+#define FMI_MINIUNZ_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int fmi_miniunz(const char* zip_file_path, const char* output_folder);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* End of header file FMI_MINIUNZ_H */
diff --git a/src/ZIP/include/FMI/fmi_minizip.h b/src/ZIP/include/FMI/fmi_minizip.h
new file mode 100644
index 000000000..6e95a2701
--- /dev/null
+++ b/src/ZIP/include/FMI/fmi_minizip.h
@@ -0,0 +1,12 @@
+#ifndef FMI_MINIZIP_H
+#define FMI_MINIZIP_H
+#ifdef __cplusplus 
+extern "C" {
+#endif
+
+int fmi_minizip(const char* zip_file_path, int n_files_to_zip, const char** files_to_zip); /* Renamed the main function */
+
+#ifdef __cplusplus 
+}
+#endif
+#endif /* End of header file FMI_MINIZIP_H */
diff --git a/src/ZIP/src/fmi_miniunz.c b/src/ZIP/src/fmi_miniunz.c
new file mode 100644
index 000000000..58ea51350
--- /dev/null
+++ b/src/ZIP/src/fmi_miniunz.c
@@ -0,0 +1,563 @@
+/*
+   miniunz.c
+   Version 1.1, February 14h, 2010
+   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+    Modifications for FMI-Library:
+        1. Changed all uses of printf to a new function minizip_printf
+        2. Renamed main function to fmi_miniunz
+*/
+
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+        #ifndef __USE_FILE_OFFSET64
+                #define __USE_FILE_OFFSET64
+        #endif
+        #ifndef __USE_LARGEFILE64
+                #define __USE_LARGEFILE64
+        #endif
+        #ifndef _LARGEFILE64_SOURCE
+                #define _LARGEFILE64_SOURCE
+        #endif
+        #ifndef _FILE_OFFSET_BIT
+                #define _FILE_OFFSET_BIT 64
+        #endif
+#endif
+
+#if defined(__APPLE__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+# include <direct.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <utime.h>
+#endif
+
+
+#include "unzip.h"
+
+#define CASESENSITIVITY (0)
+#define WRITEBUFFERSIZE (8192)
+#define MAXFILENAME (256)
+
+#ifdef _WIN32
+#define USEWIN32IOAPI
+#include "iowin32.h"
+#endif
+
+/* MODIFICATION Replace all stdout prints with this function for better control */
+static int minizip_printf( const char * format, ... )
+{
+    return 1;
+}
+
+/*
+  mini unzip, demo of unzip package
+
+  usage :
+  Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]
+
+  list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT
+    if it exists
+*/
+
+
+/* change_file_date : change the date/time of a file
+    filename : the filename of the file where date/time must be modified
+    dosdate : the new date at the MSDOS format (4 bytes)
+    tmu_date : the SAME new date at the tm_unz format */
+static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) {
+#ifdef _WIN32
+  HANDLE hFile;
+  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
+
+  hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
+                      0,NULL,OPEN_EXISTING,0,NULL);
+  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
+  DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
+  LocalFileTimeToFileTime(&ftLocal,&ftm);
+  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
+  CloseHandle(hFile);
+#else
+#if defined(__unix__) || defined(__APPLE__)
+  (void)dosdate;
+  struct utimbuf ut;
+  struct tm newdate;
+  newdate.tm_sec = tmu_date.tm_sec;
+  newdate.tm_min=tmu_date.tm_min;
+  newdate.tm_hour=tmu_date.tm_hour;
+  newdate.tm_mday=tmu_date.tm_mday;
+  newdate.tm_mon=tmu_date.tm_mon;
+  if (tmu_date.tm_year > 1900)
+      newdate.tm_year=tmu_date.tm_year - 1900;
+  else
+      newdate.tm_year=tmu_date.tm_year ;
+  newdate.tm_isdst=-1;
+
+  ut.actime=ut.modtime=mktime(&newdate);
+  utime(filename,&ut);
+#else
+  (void)filename;
+  (void)dosdate;
+  (void)tmu_date;
+#endif
+#endif
+}
+
+
+/* mymkdir and change_file_date are not 100 % portable
+   As I don't know well Unix, I wait feedback for the unix portion */
+
+static int mymkdir(const char* dirname) {
+    int ret=0;
+#ifdef _WIN32
+    ret = _mkdir(dirname);
+#elif defined(__unix__)
+    ret = mkdir (dirname,0775);
+#elif __APPLE__
+    ret = mkdir (dirname,0775);
+#else
+    (void)dirname;
+#endif
+    return ret;
+}
+
+static int makedir(const char *newdir) {
+  char *buffer ;
+  char *p;
+  size_t len = strlen(newdir);
+
+  if (len == 0)
+    return 0;
+
+  buffer = (char*)malloc(len+1);
+        if (buffer==NULL)
+        {
+                minizip_printf("Error allocating memory\n");
+                return UNZ_INTERNALERROR;
+        }
+  strcpy(buffer,newdir);
+
+  if (buffer[len-1] == '/') {
+    buffer[len-1] = '\0';
+  }
+  if (mymkdir(buffer) == 0)
+    {
+      free(buffer);
+      return 1;
+    }
+
+  p = buffer+1;
+  while (1)
+    {
+      char hold;
+
+      while(*p && *p != '\\' && *p != '/')
+        p++;
+      hold = *p;
+      *p = 0;
+      if ((mymkdir(buffer) == -1) && (errno == ENOENT))
+        {
+          minizip_printf("couldn't create directory %s\n",buffer);
+          free(buffer);
+          return 0;
+        }
+      if (hold == 0)
+        break;
+      *p++ = hold;
+    }
+  free(buffer);
+  return 1;
+}
+
+
+static void Display64BitsSize(ZPOS64_T n, int size_char) {
+  /* to avoid compatibility problem , we do here the conversion */
+  char number[21];
+  int offset=19;
+  int pos_string = 19;
+  number[20]=0;
+  for (;;) {
+      number[offset]=(char)((n%10)+'0');
+      if (number[offset] != '0')
+          pos_string=offset;
+      n/=10;
+      if (offset==0)
+          break;
+      offset--;
+  }
+  {
+      int size_display_string = 19-pos_string;
+      while (size_char > size_display_string)
+      {
+          size_char--;
+          minizip_printf(" ");
+      }
+  }
+
+  minizip_printf("%s",&number[pos_string]);
+}
+
+static int do_list(unzFile uf) {
+    uLong i;
+    unz_global_info64 gi;
+    int err;
+
+    err = unzGetGlobalInfo64(uf,&gi);
+    if (err!=UNZ_OK)
+        minizip_printf("error %d with zipfile in unzGetGlobalInfo \n",err);
+    minizip_printf("  Length  Method     Size Ratio   Date    Time   CRC-32     Name\n");
+    minizip_printf("  ------  ------     ---- -----   ----    ----   ------     ----\n");
+    for (i=0;i<gi.number_entry;i++)
+    {
+        char filename_inzip[256];
+        unz_file_info64 file_info;
+        uLong ratio=0;
+        const char *string_method = "";
+        char charCrypt=' ';
+        err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+        if (err!=UNZ_OK)
+        {
+            minizip_printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
+            break;
+        }
+        if (file_info.uncompressed_size>0)
+            ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size);
+
+        /* display a '*' if the file is encrypted */
+        if ((file_info.flag & 1) != 0)
+            charCrypt='*';
+
+        if (file_info.compression_method==0)
+            string_method="Stored";
+        else
+        if (file_info.compression_method==Z_DEFLATED)
+        {
+            uInt iLevel=(uInt)((file_info.flag & 0x6)/2);
+            if (iLevel==0)
+              string_method="Defl:N";
+            else if (iLevel==1)
+              string_method="Defl:X";
+            else if ((iLevel==2) || (iLevel==3))
+              string_method="Defl:F"; /* 2:fast , 3 : extra fast*/
+        }
+        else
+        if (file_info.compression_method==Z_BZIP2ED)
+        {
+              string_method="BZip2 ";
+        }
+        else
+            string_method="Unkn. ";
+
+        Display64BitsSize(file_info.uncompressed_size,7);
+        minizip_printf("  %6s%c",string_method,charCrypt);
+        Display64BitsSize(file_info.compressed_size,7);
+        minizip_printf(" %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
+                ratio,
+                (uLong)file_info.tmu_date.tm_mon + 1,
+                (uLong)file_info.tmu_date.tm_mday,
+                (uLong)file_info.tmu_date.tm_year % 100,
+                (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,
+                (uLong)file_info.crc,filename_inzip);
+        if ((i+1)<gi.number_entry)
+        {
+            err = unzGoToNextFile(uf);
+            if (err!=UNZ_OK)
+            {
+                minizip_printf("error %d with zipfile in unzGoToNextFile\n",err);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+
+static int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int* popt_overwrite, const char* password) {
+    char filename_inzip[256];
+    char* filename_withoutpath;
+    char* p;
+    int err=UNZ_OK;
+    FILE *fout=NULL;
+    void* buf;
+    uInt size_buf;
+
+    unz_file_info64 file_info;
+    err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+
+    if (err!=UNZ_OK)
+    {
+        minizip_printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
+        return err;
+    }
+
+    size_buf = WRITEBUFFERSIZE;
+    buf = (void*)malloc(size_buf);
+    if (buf==NULL)
+    {
+        minizip_printf("Error allocating memory\n");
+        return UNZ_INTERNALERROR;
+    }
+
+    p = filename_withoutpath = filename_inzip;
+    while ((*p) != '\0')
+    {
+        if (((*p)=='/') || ((*p)=='\\'))
+            filename_withoutpath = p+1;
+        p++;
+    }
+
+    if ((*filename_withoutpath)=='\0')
+    {
+        if ((*popt_extract_without_path)==0)
+        {
+            minizip_printf("creating directory: %s\n",filename_inzip);
+            mymkdir(filename_inzip);
+        }
+    }
+    else
+    {
+        const char* write_filename;
+        int skip=0;
+
+        if ((*popt_extract_without_path)==0)
+            write_filename = filename_inzip;
+        else
+            write_filename = filename_withoutpath;
+
+        if (write_filename[0]!='\0')
+        {
+            const char* relative_check = write_filename;
+            while (relative_check[1]!='\0')
+            {
+                if (relative_check[0]=='.' && relative_check[1]=='.')
+                    write_filename = relative_check;
+                relative_check++;
+            }
+        }
+
+        while (write_filename[0]=='/' || write_filename[0]=='.')
+            write_filename++;
+
+        err = unzOpenCurrentFilePassword(uf,password);
+        if (err!=UNZ_OK)
+        {
+            minizip_printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
+        }
+
+        if (((*popt_overwrite)==0) && (err==UNZ_OK))
+        {
+            char rep=0;
+            FILE* ftestexist;
+            ftestexist = FOPEN_FUNC(write_filename,"rb");
+            if (ftestexist!=NULL)
+            {
+                fclose(ftestexist);
+                do
+                {
+                    char answer[128];
+                    int ret;
+
+                    minizip_printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);
+                    ret = scanf("%1s",answer);
+                    if (ret != 1)
+                    {
+                       exit(EXIT_FAILURE);
+                    }
+                    rep = answer[0] ;
+                    if ((rep>='a') && (rep<='z'))
+                        rep -= 0x20;
+                }
+                while ((rep!='Y') && (rep!='N') && (rep!='A'));
+            }
+
+            if (rep == 'N')
+                skip = 1;
+
+            if (rep == 'A')
+                *popt_overwrite=1;
+        }
+
+        if ((skip==0) && (err==UNZ_OK))
+        {
+            fout=FOPEN_FUNC(write_filename,"wb");
+            /* some zipfile don't contain directory alone before file */
+            if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
+                                (filename_withoutpath!=(char*)filename_inzip))
+            {
+                char c=*(filename_withoutpath-1);
+                *(filename_withoutpath-1)='\0';
+                makedir(write_filename);
+                *(filename_withoutpath-1)=c;
+                fout=FOPEN_FUNC(write_filename,"wb");
+            }
+
+            if (fout==NULL)
+            {
+                minizip_printf("error opening %s\n",write_filename);
+            }
+        }
+
+        if (fout!=NULL)
+        {
+            minizip_printf(" extracting: %s\n",write_filename);
+
+            do
+            {
+                err = unzReadCurrentFile(uf,buf,size_buf);
+                if (err<0)
+                {
+                    minizip_printf("error %d with zipfile in unzReadCurrentFile\n",err);
+                    break;
+                }
+                if (err>0)
+                    if (fwrite(buf,(unsigned)err,1,fout)!=1)
+                    {
+                        minizip_printf("error in writing extracted file\n");
+                        err=UNZ_ERRNO;
+                        break;
+                    }
+            }
+            while (err>0);
+            if (fout)
+                    fclose(fout);
+
+            if (err==0)
+                change_file_date(write_filename,file_info.dosDate,
+                                 file_info.tmu_date);
+        }
+
+        if (err==UNZ_OK)
+        {
+            err = unzCloseCurrentFile (uf);
+            if (err!=UNZ_OK)
+            {
+                minizip_printf("error %d with zipfile in unzCloseCurrentFile\n",err);
+            }
+        }
+        else
+            unzCloseCurrentFile(uf); /* don't lose the error */
+    }
+
+    free(buf);
+    return err;
+}
+
+
+static int do_extract(unzFile uf, int opt_extract_without_path, int opt_overwrite, const char* password) {
+    uLong i;
+    unz_global_info64 gi;
+    int err;
+
+    err = unzGetGlobalInfo64(uf,&gi);
+    if (err!=UNZ_OK)
+        minizip_printf("error %d with zipfile in unzGetGlobalInfo \n",err);
+
+    for (i=0;i<gi.number_entry;i++)
+    {
+        if (do_extract_currentfile(uf,&opt_extract_without_path,
+                                      &opt_overwrite,
+                                      password) != UNZ_OK)
+            break;
+
+        if ((i+1)<gi.number_entry)
+        {
+            err = unzGoToNextFile(uf);
+            if (err!=UNZ_OK)
+            {
+                minizip_printf("error %d with zipfile in unzGoToNextFile\n",err);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+
+
+int fmi_miniunz(const char* zipfilename, const char* dirname) {
+    char filename_try[MAXFILENAME+16] = "";
+    int ret_value=0;
+    unzFile uf=NULL;
+
+
+    if (zipfilename!=NULL)
+    {
+
+#        ifdef USEWIN32IOAPI
+        zlib_filefunc64_def ffunc;
+#        endif
+
+        strncpy(filename_try, zipfilename,MAXFILENAME-1);
+        /* strncpy doesn't append the trailing NULL, of the string is too long. */
+        filename_try[ MAXFILENAME ] = '\0';
+
+#        ifdef USEWIN32IOAPI
+        fill_win32_filefunc64A(&ffunc);
+        uf = unzOpen2_64(zipfilename,&ffunc);
+#        else
+        uf = unzOpen64(zipfilename);
+#        endif
+        if (uf==NULL)
+        {
+            strcat(filename_try,".zip");
+#            ifdef USEWIN32IOAPI
+            uf = unzOpen2_64(filename_try,&ffunc);
+#            else
+            uf = unzOpen64(filename_try);
+#            endif
+        }
+    }
+
+    if (uf==NULL)
+    {
+        minizip_printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename);
+        return 1;
+    }
+    minizip_printf("%s opened\n",filename_try);
+
+
+#ifdef _WIN32
+    if (_chdir(dirname))
+#else
+    if (chdir(dirname))
+#endif
+    {
+      minizip_printf("Error changing into %s, aborting\n", dirname);
+      exit(-1);
+    }
+
+    ret_value = do_extract(uf, 0, 1, NULL);
+
+    unzClose(uf);
+
+    return ret_value;
+}
diff --git a/src/ZIP/src/fmi_minizip.c b/src/ZIP/src/fmi_minizip.c
new file mode 100644
index 000000000..be266bb70
--- /dev/null
+++ b/src/ZIP/src/fmi_minizip.c
@@ -0,0 +1,424 @@
+/*
+   minizip.c
+   Version 1.1, February 14h, 2010
+   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+    Modifications for FMI-Library:
+        1. Changed all uses of printf to a new function minizip_printf
+        2. Renamed main function to fmi_minizip
+*/
+
+
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+        #ifndef __USE_FILE_OFFSET64
+                #define __USE_FILE_OFFSET64
+        #endif
+        #ifndef __USE_LARGEFILE64
+                #define __USE_LARGEFILE64
+        #endif
+        #ifndef _LARGEFILE64_SOURCE
+                #define _LARGEFILE64_SOURCE
+        #endif
+        #ifndef _FILE_OFFSET_BIT
+                #define _FILE_OFFSET_BIT 64
+        #endif
+#endif
+
+#if defined(__APPLE__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifdef _WIN32
+# include <direct.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <utime.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+
+#include "zip.h"
+
+#ifdef _WIN32
+        #define USEWIN32IOAPI
+        #include "iowin32.h"
+#endif
+
+
+
+#define WRITEBUFFERSIZE (16384)
+#define MAXFILENAME (256)
+
+/* MODIFICATION Replace all stdout prints with this function for better control */
+static int minizip_printf( const char * format, ... )
+{
+    return 1;
+}
+
+#ifdef _WIN32
+/* f: name of file to get info on, tmzip: return value: access,
+   modification and creation times, dt: dostime */
+static int filetime(const char *f, tm_zip *tmzip, uLong *dt) {
+  int ret = 0;
+  {
+      FILETIME ftLocal;
+      HANDLE hFind;
+      WIN32_FIND_DATAA ff32;
+
+      hFind = FindFirstFileA(f,&ff32);
+      if (hFind != INVALID_HANDLE_VALUE)
+      {
+        FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
+        FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
+        FindClose(hFind);
+        ret = 1;
+      }
+  }
+  return ret;
+}
+#else
+#if defined(__unix__) || defined(__APPLE__)
+/* f: name of file to get info on, tmzip: return value: access,
+   modification and creation times, dt: dostime */
+static int filetime(const char *f, tm_zip *tmzip, uLong *dt) {
+  (void)dt;
+  int ret=0;
+  struct stat s;        /* results of stat() */
+  struct tm* filedate;
+  time_t tm_t=0;
+
+  if (strcmp(f,"-")!=0)
+  {
+    char name[MAXFILENAME+1];
+    size_t len = strlen(f);
+    if (len > MAXFILENAME)
+      len = MAXFILENAME;
+
+    strncpy(name, f,MAXFILENAME-1);
+    /* strncpy doesn't append the trailing NULL, of the string is too long. */
+    name[ MAXFILENAME ] = '\0';
+
+    if (name[len - 1] == '/')
+      name[len - 1] = '\0';
+    /* not all systems allow stat'ing a file with / appended */
+    if (stat(name,&s)==0)
+    {
+      tm_t = s.st_mtime;
+      ret = 1;
+    }
+  }
+  filedate = localtime(&tm_t);
+
+  tmzip->tm_sec  = filedate->tm_sec;
+  tmzip->tm_min  = filedate->tm_min;
+  tmzip->tm_hour = filedate->tm_hour;
+  tmzip->tm_mday = filedate->tm_mday;
+  tmzip->tm_mon  = filedate->tm_mon ;
+  tmzip->tm_year = filedate->tm_year;
+
+  return ret;
+}
+#else
+/* f: name of file to get info on, tmzip: return value: access,
+   modification and creation times, dt: dostime */
+static int filetime(const char *f, tm_zip *tmzip, uLong *dt) {
+    (void)f;
+    (void)tmzip;
+    (void)dt;
+    return 0;
+}
+#endif
+#endif
+
+
+
+
+static int check_exist_file(const char* filename) {
+    FILE* ftestexist;
+    int ret = 1;
+    ftestexist = FOPEN_FUNC(filename,"rb");
+    if (ftestexist==NULL)
+        ret = 0;
+    else
+        fclose(ftestexist);
+    return ret;
+}
+
+/* calculate the CRC32 of a file,
+   because to encrypt a file, we need known the CRC32 of the file before */
+static int getFileCrc(const char* filenameinzip, void* buf, unsigned long size_buf, unsigned long* result_crc) {
+   unsigned long calculate_crc=0;
+   int err=ZIP_OK;
+   FILE * fin = FOPEN_FUNC(filenameinzip,"rb");
+
+   unsigned long size_read = 0;
+   /* unsigned long total_read = 0; */
+   if (fin==NULL)
+   {
+       err = ZIP_ERRNO;
+   }
+
+    if (err == ZIP_OK)
+        do
+        {
+            err = ZIP_OK;
+            size_read = fread(buf,1,size_buf,fin);
+            if (size_read < size_buf)
+                if (feof(fin)==0)
+            {
+                minizip_printf("error in reading %s\n",filenameinzip);
+                err = ZIP_ERRNO;
+            }
+
+            if (size_read>0)
+                calculate_crc = crc32_z(calculate_crc,buf,size_read);
+            /* total_read += size_read; */
+
+        } while ((err == ZIP_OK) && (size_read>0));
+
+    if (fin)
+        fclose(fin);
+
+    *result_crc=calculate_crc;
+    minizip_printf("file %s crc %lx\n", filenameinzip, calculate_crc);
+    return err;
+}
+
+static int isLargeFile(const char* filename) {
+  int largeFile = 0;
+  ZPOS64_T pos = 0;
+  FILE* pFile = FOPEN_FUNC(filename, "rb");
+
+  if(pFile != NULL)
+  {
+    FSEEKO_FUNC(pFile, 0, SEEK_END);
+    pos = (ZPOS64_T)FTELLO_FUNC(pFile);
+
+                minizip_printf("File : %s is %llu bytes\n", filename, pos);
+
+    if(pos >= 0xffffffff)
+     largeFile = 1;
+
+                fclose(pFile);
+  }
+
+ return largeFile;
+}
+
+int fmi_minizip(const char* zip_file_path, int n_files_to_zip, const char** files_to_zip) {
+    int i;
+    int opt_overwrite=1;
+    int opt_compress_level=1;
+    char filename_try[MAXFILENAME+16];
+    int zipok = 1;
+    int err=0;
+    size_t size_buf=0;
+    void* buf=NULL;
+    const char* password=NULL;
+
+    size_buf = WRITEBUFFERSIZE;
+    buf = (void*)malloc(size_buf);
+    if (buf==NULL)
+    {
+        minizip_printf("Error allocating memory\n");
+        return ZIP_INTERNALERROR;
+    }
+
+
+    int len;
+    int dot_found=0;
+
+    strncpy(filename_try, zip_file_path, MAXFILENAME-1);
+    /* strncpy doesn't append the trailing NULL, of the string is too long. */
+    filename_try[ MAXFILENAME ] = '\0';
+
+    len=(int)strlen(filename_try);
+    for (i=0;i<len;i++)
+        if (filename_try[i]=='.')
+            dot_found=1;
+
+    if (dot_found==0)
+        strcat(filename_try,".zip");
+
+    if (opt_overwrite==2)
+    {
+        /* if the file don't exist, we not append file */
+        if (check_exist_file(filename_try)==0)
+            opt_overwrite=1;
+    }
+    else
+    if (opt_overwrite==0)
+        if (check_exist_file(filename_try)!=0)
+        {
+            char rep=0;
+            do
+            {
+                char answer[128];
+                int ret;
+                minizip_printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);
+                ret = scanf("%1s",answer);
+                if (ret != 1)
+                {
+                    exit(EXIT_FAILURE);
+                }
+                rep = answer[0] ;
+                if ((rep>='a') && (rep<='z'))
+                    rep -= 0x20;
+            }
+            while ((rep!='Y') && (rep!='N') && (rep!='A'));
+            if (rep=='N')
+                zipok = 0;
+            if (rep=='A')
+                opt_overwrite = 2;
+        }
+
+    if (zipok==1)
+    {
+        zipFile zf;
+        int errclose;
+#        ifdef USEWIN32IOAPI
+        zlib_filefunc64_def ffunc;
+        fill_win32_filefunc64A(&ffunc);
+        zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
+#        else
+        zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0);
+#        endif
+
+        if (zf == NULL)
+        {
+            minizip_printf("error opening %s\n",filename_try);
+            err= ZIP_ERRNO;
+        }
+        else
+            minizip_printf("creating %s\n",filename_try);
+
+        for (i=0;(i<n_files_to_zip) && (err==ZIP_OK);i++)
+        {
+            {
+                FILE * fin = NULL;
+                size_t size_read;
+                const char* filenameinzip = files_to_zip[i];
+                const char *savefilenameinzip;
+                zip_fileinfo zi;
+                unsigned long crcFile=0;
+                int zip64 = 0;
+
+                zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
+                zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
+                zi.dosDate = 0;
+                zi.internal_fa = 0;
+                zi.external_fa = 0;
+                filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
+
+/*
+                err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
+                                 NULL,0,NULL,0,NULL / * comment * /,
+                                 (opt_compress_level != 0) ? Z_DEFLATED : 0,
+                                 opt_compress_level);
+*/
+                if ((password != NULL) && (err==ZIP_OK))
+                    err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
+
+                zip64 = isLargeFile(filenameinzip);
+
+                                                         /* The path name saved, should not include a leading slash. */
+               /*if it did, windows/xp and dynazip couldn't read the zip file. */
+                 savefilenameinzip = filenameinzip;
+                 while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' )
+                 {
+                     savefilenameinzip++;
+                 }
+
+                 /**/
+                err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi,
+                                 NULL,0,NULL,0,NULL /* comment*/,
+                                 (opt_compress_level != 0) ? Z_DEFLATED : 0,
+                                 opt_compress_level,0,
+                                 /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+                                 password,crcFile, zip64);
+
+                if (err != ZIP_OK)
+                    minizip_printf("error in opening %s in zipfile\n",filenameinzip);
+                else
+                {
+                    fin = FOPEN_FUNC(filenameinzip,"rb");
+                    if (fin==NULL)
+                    {
+                        err=ZIP_ERRNO;
+                        minizip_printf("error in opening %s for reading\n",filenameinzip);
+                    }
+                }
+
+                if (err == ZIP_OK)
+                    do
+                    {
+                        err = ZIP_OK;
+                        size_read = fread(buf,1,size_buf,fin);
+                        if (size_read < size_buf)
+                            if (feof(fin)==0)
+                        {
+                            minizip_printf("error in reading %s\n",filenameinzip);
+                            err = ZIP_ERRNO;
+                        }
+
+                        if (size_read>0)
+                        {
+                            err = zipWriteInFileInZip (zf,buf,(unsigned)size_read);
+                            if (err<0)
+                            {
+                                minizip_printf("error in writing %s in the zipfile\n",
+                                                 filenameinzip);
+                            }
+
+                        }
+                    } while ((err == ZIP_OK) && (size_read>0));
+
+                if (fin)
+                    fclose(fin);
+
+                if (err<0)
+                    err=ZIP_ERRNO;
+                else
+                {
+                    err = zipCloseFileInZip(zf);
+                    if (err!=ZIP_OK)
+                        minizip_printf("error in closing %s in the zipfile\n",
+                                    filenameinzip);
+                }
+            }
+        }
+        errclose = zipClose(zf,NULL);
+        if (errclose != ZIP_OK)
+            minizip_printf("error in closing %s\n",filename_try);
+    }
+
+
+    free(buf);
+    return 0;
+}
diff --git a/src/ZIP/src/fmi_zip_unzip.c b/src/ZIP/src/fmi_zip_unzip.c
index 9950029c2..8611c26dd 100644
--- a/src/ZIP/src/fmi_zip_unzip.c
+++ b/src/ZIP/src/fmi_zip_unzip.c
@@ -20,7 +20,7 @@ extern "C" {
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <miniunz.h>
+#include "FMI/fmi_miniunz.h"
 
 #include <JM/jm_types.h>
 #include <JM/jm_callbacks.h>
@@ -30,47 +30,27 @@ static const char* module = "FMIZIP";
 
 jm_status_enu_t fmi_zip_unzip(const char* zip_file_path, const char* output_folder, jm_callbacks* callbacks)
 {
-    /*
-    Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]
-      -e  Extract without pathname (junk paths)
-      -x  Extract with pathname
-      -v  list files
-      -l  list files
-      -d  directory to extract into
-      -o  overwrite files without prompting
-      -p  extract crypted file using password
-    */
-
     /* A call to minunz may change the current directory and therefore we must change it back */
     char cd[FILENAME_MAX];
 
-    int argc = 6;
-    const char *argv[6];
     int status;
 
     jm_log_verbose(callbacks, module, "Unpacking FMU into %s", output_folder);
 
-    argv[0]="miniunz";
-    argv[1]="-x";
-    argv[2]="-o";
-    argv[3]=zip_file_path;
-    argv[4]="-d";
-    argv[5]=output_folder;
-
 
     /* Temporary save the current directory */
     if (jm_portability_get_current_working_directory(cd, sizeof(cd) / sizeof(char)) == jm_status_error) {
-        jm_log_fatal(callbacks, module, "Could not get Current Directory");
+        jm_log_fatal(callbacks, module, "Could not get Current Directory");
         return jm_status_error;
     }
 
     /* Unzip */
-    status = miniunz(argc, (char**)argv);
+    status = fmi_miniunz(zip_file_path, output_folder);
 
     /* Reset the current directory */
-    if (jm_portability_set_current_working_directory(cd) == jm_status_error) {
-        jm_log_warning(callbacks, module, "Could not restore Current Directory after unpacking");
-        return jm_status_warning;
+    if (jm_portability_set_current_working_directory(cd) == jm_status_error) {
+        jm_log_warning(callbacks, module, "Could not restore Current Directory after unpacking");
+        return jm_status_warning;
     }
 
     /* Return error status */
@@ -84,4 +64,4 @@ jm_status_enu_t fmi_zip_unzip(const char* zip_file_path, const char* output_fold
 
 #ifdef __cplusplus 
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/ZIP/src/fmi_zip_zip.c b/src/ZIP/src/fmi_zip_zip.c
index 6d4413dda..cab2e19fa 100644
--- a/src/ZIP/src/fmi_zip_zip.c
+++ b/src/ZIP/src/fmi_zip_zip.c
@@ -15,7 +15,8 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <minizip.h>
+
+#include "FMI/fmi_minizip.h"
 
 #include <JM/jm_types.h>
 #include <JM/jm_callbacks.h>
@@ -25,61 +26,21 @@ jm_status_enu_t fmi_zip_zip(const char* zip_file_path, int n_files_to_zip, const
 {
     /* A call to minizip may change the current directory and therefore we must change it back */
     char cd[FILENAME_MAX];
-
-#define N_BASIC_ARGS 4
-    int argc;
-    char** argv;
-    int k;
     int status;
 
     /* Temporary save the current directory */
     if (jm_portability_get_current_working_directory(cd, sizeof(cd) / sizeof(char)) == jm_status_error) {
-        jm_log(callbacks, "UNZIP", jm_log_level_error, "Could not get Current Directory");
-        return jm_status_error;
-    }
-
-    argc = N_BASIC_ARGS + n_files_to_zip;
-    argv = callbacks->calloc(sizeof(char*), argc);
-    /* Failed to allocate memory, return error */
-    if (argv == NULL) {
-        callbacks->logger(NULL, "FMIZIP", jm_log_level_error, "Failed to allocate memory.");
+        jm_log(callbacks, "UNZIP", jm_log_level_error, "Could not get Current Directory");
         return jm_status_error;
     }
 
-    /* Input arguments to the corresponding minizip main() function call */
-    /*
-    Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]
-
-    -o  Overwrite existing file.zip
-    -a  Append to existing file.zip
-    -0  Store only
-    -1  Compress faster
-    -9  Compress better
-
-    -j  exclude path. store only the file name.
-    */
-    argv[0]="minizip";
-    argv[1]="-o";
-    argv[2]="-1";
-    argv[3]=(char*)zip_file_path;
-
-    /* Append the input argument list with the files to unzip */
-    jm_log_info(callbacks, "FMIZIP", "Will compress following files: \n");
-    for (k = 0; k < n_files_to_zip; k++) {
-        jm_log_info(callbacks, "FMIZIP", "\t%s\n", files_to_zip[k]);
-        argv[N_BASIC_ARGS + k] = (char*)files_to_zip[k];
-    }
-
     /* Zip */
-    status = minizip(argc, (char**)argv);
-
-    /* Free allocated memory */
-    callbacks->free(argv);
+    status = fmi_minizip(zip_file_path, n_files_to_zip, files_to_zip);
 
     /* Reset the current directory */
-    if (jm_portability_set_current_working_directory(cd) == jm_status_error) {
-        jm_log(callbacks, "UNZIP", jm_log_level_warning, "Could not change back Current Directory");
-        return jm_status_warning;
+    if (jm_portability_set_current_working_directory(cd) == jm_status_error) {
+        jm_log(callbacks, "UNZIP", jm_log_level_warning, "Could not change back Current Directory");
+        return jm_status_warning;
     }
 
     /* Return error status */


Reviews:
user: login: filip-stenstrom
body: I think overall this looks good. There are a few minor comments, and I also need to verify a few things internally.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-08T15:04:39Z
user: login: jschueller
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T15:40:35Z
user: login: jschueller
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T15:48:35Z
user: login: jschueller
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T16:00:55Z
user: login: filip-stenstrom
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-12T13:22:59Z
user: login: jschueller
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T16:24:18Z
user: login: jschueller
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T17:07:49Z
user: login: filip-stenstrom
body: Looks good!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-13T15:41:14Z

Review comments:
diff_hunk: @@ -48,9 +48,15 @@ endif()
 option(FMILIB_BUILD_STATIC_LIB "Build the library as static." ON)
 option(FMILIB_BUILD_SHARED_LIB "Build the library as shared (dll/so/dylib)." ON)
 option(FMILIB_INSTALL_SUBLIBS  "Install sub-libraries (fmicapi. fmixml, jmutil, fmiimport, fmizip)" OFF)
-option(FMILIB_FIND_PACKAGE_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_MINIZIP "Use system minizp library instead of the one in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle minizip." OFF)
path: CMakeLists.txt
user: login: filip-stenstrom
body: ```suggestion
option(FMILIB_SYSTEM_MINIZIP "Use system minizip library instead of the one in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle minizip." OFF)
```
created_at: 2025-05-07T14:50:13Z
author_association: COLLABORATOR
diff_hunk: @@ -48,9 +48,15 @@ endif()
 option(FMILIB_BUILD_STATIC_LIB "Build the library as static." ON)
 option(FMILIB_BUILD_SHARED_LIB "Build the library as shared (dll/so/dylib)." ON)
 option(FMILIB_INSTALL_SUBLIBS  "Install sub-libraries (fmicapi. fmixml, jmutil, fmiimport, fmizip)" OFF)
-option(FMILIB_FIND_PACKAGE_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
path: CMakeLists.txt
user: login: filip-stenstrom
body: Not certain we want to rename public variables due to breaking old builds. I get why we would want to do it though. I'll get back with more info on this.
created_at: 2025-05-07T14:57:37Z
author_association: COLLABORATOR
diff_hunk: @@ -48,9 +48,15 @@ endif()
 option(FMILIB_BUILD_STATIC_LIB "Build the library as static." ON)
 option(FMILIB_BUILD_SHARED_LIB "Build the library as shared (dll/so/dylib)." ON)
 option(FMILIB_INSTALL_SUBLIBS  "Install sub-libraries (fmicapi. fmixml, jmutil, fmiimport, fmizip)" OFF)
-option(FMILIB_FIND_PACKAGE_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_MINIZIP "Use system minizp library instead of the one in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle minizip." OFF)
 option(FMILIB_SYSTEM_EXPAT "Use system expat library instead of the one in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle expat." OFF)
-mark_as_advanced(FMILIB_FIND_PACKAGE_ZLIB)
+option(FMILIB_EXTERNAL_LIBS "Use system libraries" OFF)
path: CMakeLists.txt
user: login: filip-stenstrom
body: ```suggestion
option(FMILIB_EXTERNAL_LIBS "Use system libraries for all dependencies instead of the ones in FMILibrary/Thirdparty" OFF)
```
created_at: 2025-05-07T14:59:14Z
author_association: COLLABORATOR
diff_hunk: @@ -48,9 +48,15 @@ endif()
 option(FMILIB_BUILD_STATIC_LIB "Build the library as static." ON)
 option(FMILIB_BUILD_SHARED_LIB "Build the library as shared (dll/so/dylib)." ON)
 option(FMILIB_INSTALL_SUBLIBS  "Install sub-libraries (fmicapi. fmixml, jmutil, fmiimport, fmizip)" OFF)
-option(FMILIB_FIND_PACKAGE_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
path: CMakeLists.txt
user: login: filip-stenstrom
body: ```suggestion
option(FMILIB_SYSTEM_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle zlib." OFF)
```
created_at: 2025-05-07T15:13:23Z
author_association: COLLABORATOR
diff_hunk: @@ -48,9 +48,15 @@ endif()
 option(FMILIB_BUILD_STATIC_LIB "Build the library as static." ON)
 option(FMILIB_BUILD_SHARED_LIB "Build the library as shared (dll/so/dylib)." ON)
 option(FMILIB_INSTALL_SUBLIBS  "Install sub-libraries (fmicapi. fmixml, jmutil, fmiimport, fmizip)" OFF)
-option(FMILIB_FIND_PACKAGE_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_MINIZIP "Use system minizp library instead of the one in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle minizip." OFF)
 option(FMILIB_SYSTEM_EXPAT "Use system expat library instead of the one in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle expat." OFF)
-mark_as_advanced(FMILIB_FIND_PACKAGE_ZLIB)
+option(FMILIB_EXTERNAL_LIBS "Use system libraries" OFF)
+if (FMILIB_EXTERNAL_LIBS)
path: CMakeLists.txt
user: login: filip-stenstrom
body: We don't have any space between the command (or `if` etc.) and the `(` in the CMakeLists in our code style.

So here it should be `if(FMILIB_EXTERNAL_LIBS)`.

Please brief through the changes and fix it everywhere (mainly for `if`, `else` and `endif` from what I can see).
created_at: 2025-05-07T15:20:53Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,21 @@
+# Find the Minizip library
+# Defines:
+
+#  MINIZIP_INCLUDE_DIR - minizip include directory
+#  MINIZIP_LIBRARY     - minizip library file
+#  MINIZIP_FOUND       - TRUE if minizip is found
+
+find_path(MINIZIP_INCLUDE_DIR NAMES unzip.h PATH_SUFFIXES minizip)
+
+if (MINIZIP_USE_STATIC_LIBS)
+  find_library(MINIZIP_LIBRARY NAMES ${CMAKE_STATIC_LIBRARY_PREFIX}minizip${CMAKE_STATIC_LIBRARY_SUFFIX} minizip)
+else ()
+  find_library(MINIZIP_LIBRARY NAMES minizip)
+endif ()
+
+if(MINIZIP_INCLUDE_DIR AND MINIZIP_LIBRARY)
+  set(MINIZIP_FOUND TRUE)
+endif ()
path: Config.cmake/FindMiniZip.cmake
user: login: filip-stenstrom
body: These lines can be removed I believe since variable will be set by `find_package_handle_standard_args` https://cmake.org/cmake/help/latest/module/FindPackageHandleStandardArgs.html

![image](https://github.com/user-attachments/assets/5c4cdfd3-3826-478a-a804-605d4ef32144)

...

![image](https://github.com/user-attachments/assets/e6babbd4-9ef6-4eeb-9380-9ec3c65315aa)

created_at: 2025-05-08T07:28:47Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,21 @@
+# Find the Minizip library
+# Defines:
+
+#  MINIZIP_INCLUDE_DIR - minizip include directory
+#  MINIZIP_LIBRARY     - minizip library file
+#  MINIZIP_FOUND       - TRUE if minizip is found
+
+find_path(MINIZIP_INCLUDE_DIR NAMES unzip.h PATH_SUFFIXES minizip)
+
+if (MINIZIP_USE_STATIC_LIBS)
path: Config.cmake/FindMiniZip.cmake
user: login: filip-stenstrom
body: Where do we define MINIZIP_USE_STATIC_LIBS or is it some auto-generated variable?
created_at: 2025-05-08T07:43:51Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,654 @@
+/*
path: src/ZIP/src/fmi_miniunz.c
user: login: filip-stenstrom
body: A few things:

1. Let's update ThirdParty/Minizip/README.txt. I suggest:

```
The sources for minizip are copied from: https://github.com/madler/zlib/releases/tag/v1.3.1

Additionally:
1. miniunz.c and minizip.c has been copied to fmi-library/src/ZIP/src/{fmi_miniunz.c,fmi_minizip.c}
2. The above mentioned copied files have also been altered. See the file-level comment in each file for details.
```

2. Let's write the modifications in these .c files since they're now no longer located in minizip. I've added suggestions in other threads.
3. There are some concerns about mixing Modelon files and ThirdParty files. We've tried to keep them separated by using the ThirdParty directory. But I realize this is the easiest way to do this. Otherwise we'd need some `ThirdParty/MinizipImpl` library, which would not be nice, especially since it's just two files. I'll get back with more info on this.
4. Just a comment, but it's not very nice that if vulnerabilities are found and patched in any of these files, and a user updates their system-minizip, then it still won't be fixed, which is not intuitive. However, we don't have much of a choice here, except implementing our own "miniunz.c" etc., which would likely have its own issues.
created_at: 2025-05-08T14:55:21Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,654 @@
+/*
+   miniunz.c
+   Version 1.1, February 14h, 2010
+   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
path: src/ZIP/src/fmi_miniunz.c
user: login: filip-stenstrom
body: ```suggestion
         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
         
    Modifications for FMI-Library:
        1. Changed all uses of printf to a new function minizip_printf
        2. Renamed main function to fmi_miniunz
```
created_at: 2025-05-08T14:58:14Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,515 @@
+/*
+   minizip.c
+   Version 1.1, February 14h, 2010
+   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
path: src/ZIP/src/fmi_minizip.c
user: login: filip-stenstrom
body: ```suggestion
         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
         
    Modifications for FMI-Library:
        1. Changed all uses of printf to a new function minizip_printf
        2. Renamed main function to fmi_minizip
```
created_at: 2025-05-08T14:59:06Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,21 @@
+# Find the Minizip library
+# Defines:
+
+#  MINIZIP_INCLUDE_DIR - minizip include directory
+#  MINIZIP_LIBRARY     - minizip library file
+#  MINIZIP_FOUND       - TRUE if minizip is found
+
+find_path(MINIZIP_INCLUDE_DIR NAMES unzip.h PATH_SUFFIXES minizip)
+
+if (MINIZIP_USE_STATIC_LIBS)
path: Config.cmake/FindMiniZip.cmake
user: login: jschueller
body: it can be specified from cmake command-line to prefer static libs, but its optional
created_at: 2025-05-08T15:40:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -48,9 +48,15 @@ endif()
 option(FMILIB_BUILD_STATIC_LIB "Build the library as static." ON)
 option(FMILIB_BUILD_SHARED_LIB "Build the library as shared (dll/so/dylib)." ON)
 option(FMILIB_INSTALL_SUBLIBS  "Install sub-libraries (fmicapi. fmixml, jmutil, fmiimport, fmizip)" OFF)
-option(FMILIB_FIND_PACKAGE_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
path: CMakeLists.txt
user: login: jschueller
body: we can raise an error here if the old variable is used
created_at: 2025-05-08T15:48:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,654 @@
+/*
path: src/ZIP/src/fmi_miniunz.c
user: login: jschueller
body: 3. the license is compatible
created_at: 2025-05-08T16:00:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -48,9 +48,18 @@ endif()
 option(FMILIB_BUILD_STATIC_LIB "Build the library as static." ON)
 option(FMILIB_BUILD_SHARED_LIB "Build the library as shared (dll/so/dylib)." ON)
 option(FMILIB_INSTALL_SUBLIBS  "Install sub-libraries (fmicapi. fmixml, jmutil, fmiimport, fmizip)" OFF)
-option(FMILIB_FIND_PACKAGE_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_ZLIB "Use find_package for zlib, instead of version in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle zlib." OFF)
+if(DEFINED FMILIB_FIND_PACKAGE_ZLIB)
+    message(SEND_ERROR "FMILIB_FIND_PACKAGE_ZLIB is deprecated, use FMILIB_SYSTEM_ZLIB")
path: CMakeLists.txt
user: login: filip-stenstrom
body: ```suggestion
    message(SEND_ERROR "FMILIB_FIND_PACKAGE_ZLIB is obsolete, use FMILIB_SYSTEM_ZLIB")
```

I think this is fine, but we could've also had a transition period where this option if set would just set the SYSTEM one. But given that we also now will require later CMake, at least the build system breaking changes will happen at the same time.

There should also be a point in the release notes about this, e.g. just `CMake option FMILIB_FIND_PACKAGE_ZLIB is now obsolete, use FMILIB_SYSTEM_ZLIB instead`
created_at: 2025-05-12T08:41:00Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,654 @@
+/*
path: src/ZIP/src/fmi_miniunz.c
user: login: filip-stenstrom
body: 3. Not only about license, but about keeping track of what is external to make it clear that we need to update alteration lists etc. But we've discussed this and it's OK in this case.

We'd however like to remove all unused functionality of the two files, e.g. code for argument processing and args that aren't used (e.g. listing contents of zip).

If you want to do that in this PR that would be good, otherwise we'll do it soon in another PR, in the coming weeks.
created_at: 2025-05-12T13:22:19Z
author_association: COLLABORATOR
diff_hunk: @@ -48,9 +48,18 @@ endif()
 option(FMILIB_BUILD_STATIC_LIB "Build the library as static." ON)
 option(FMILIB_BUILD_SHARED_LIB "Build the library as shared (dll/so/dylib)." ON)
 option(FMILIB_INSTALL_SUBLIBS  "Install sub-libraries (fmicapi. fmixml, jmutil, fmiimport, fmizip)" OFF)
-option(FMILIB_FIND_PACKAGE_ZLIB  "Use find_package for zlib, instead of version in FMILibrary/Thirdparty." OFF)
+option(FMILIB_SYSTEM_ZLIB "Use find_package for zlib, instead of version in FMILibrary/Thirdparty. Static builds of FMI Library will not bundle zlib." OFF)
+if(DEFINED FMILIB_FIND_PACKAGE_ZLIB)
+    message(SEND_ERROR "FMILIB_FIND_PACKAGE_ZLIB is deprecated, use FMILIB_SYSTEM_ZLIB")
path: CMakeLists.txt
user: login: jschueller
body: done
created_at: 2025-05-12T16:24:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,654 @@
+/*
path: src/ZIP/src/fmi_miniunz.c
user: login: jschueller
body: yes, I removed the argument processing
created_at: 2025-05-12T17:07:49Z
author_association: CONTRIBUTOR

PR comments:
user: login: jschueller
created_at: 2025-05-06T14:38:04Z
body: @filip-stenstrom what about this one ?
author_association: CONTRIBUTOR
user: login: filip-stenstrom
created_at: 2025-05-06T14:49:54Z
body: > @filip-stenstrom what about this one ?

There seems to be some build issues right now. But I'll try to review this tomorrow.
author_association: COLLABORATOR
user: login: jschueller
created_at: 2025-05-06T15:53:27Z
body: > > @filip-stenstrom what about this one ?
> 
> There seems to be some build issues right now. But I'll try to review this tomorrow.

yes its ok now
author_association: CONTRIBUTOR
user: login: filip-stenstrom
created_at: 2025-05-07T15:15:58Z
body: > > > @filip-stenstrom what about this one ?
> > 
> > 
> > There seems to be some build issues right now. But I'll try to review this tomorrow.
> 
> yes its ok now

FYI I've started reviewing, will continue tomorrow.
author_association: COLLABORATOR