New Upstream Release - unshield

Ready changes

Summary

Merged new upstream version: 1.5.1 (was: 1.4.2).

Resulting package

Built on 2022-03-19T06:03 (took 1m56s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases libunshield-devapt install -t fresh-releases libunshield0-dbgsymapt install -t fresh-releases libunshield0apt install -t fresh-releases unshield-dbgsymapt install -t fresh-releases unshield

Lintian Result

Diff

diff --git a/.appveyor-linux.yml b/.appveyor-linux.yml
new file mode 100644
index 0000000..dbd11c8
--- /dev/null
+++ b/.appveyor-linux.yml
@@ -0,0 +1,67 @@
+image: Ubuntu
+
+environment:
+  matrix:
+    - CC: clang
+      CXX: clang++
+    - CC: gcc
+      CXX: g++
+
+configuration:
+  - Debug
+  - Release
+
+for:
+  -
+    matrix:
+      only:
+        - configuration: Debug
+          CC: clang
+    environment:
+      CFLAGS: -Og -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic
+      CXXFLAGS: -Og -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic
+
+  -
+    matrix:
+      only:
+        - configuration: Release
+          CC: clang
+    environment:
+      CFLAGS: -O2
+      CXXFLAGS: -O2
+
+  -
+    matrix:
+      only:
+        - configuration: Debug
+          CC: gcc
+    environment:
+      CFLAGS: -Og -g -Wall -Wextra
+      CXXFLAGS: -Og -g -Wall -Wextra
+
+  -
+    matrix:
+      only:
+        - configuration: Release
+          CC: gcc
+    environment:
+      CFLAGS: -O2
+      CXXFLAGS: -O2
+
+init:
+  - $CC --version
+  - $CXX --version
+  - cmake --version
+
+before_build:
+  - cd $APPVEYOR_BUILD_FOLDER
+  - mkdir build
+  - cd build
+
+build_script:
+  - cmake .. -DCMAKE_BUILD_TYPE=$configuration -DCMAKE_INSTALL_PREFIX=/var/tmp/unshield
+  - cmake --build .
+  - cmake --install .
+
+test_script:
+  - ../run-tests.sh
diff --git a/.appveyor-windows.yml b/.appveyor-windows.yml
new file mode 100644
index 0000000..b82366f
--- /dev/null
+++ b/.appveyor-windows.yml
@@ -0,0 +1,213 @@
+image: Visual Studio 2019
+
+cache: C:\Tools\vcpkg\installed\
+
+environment:
+  APPVEYOR_SAVE_CACHE_ON_ERROR: true
+  matrix:
+    - compiler: clang
+    - compiler: msvc
+    - compiler: gcc
+
+platform:
+  - x86-windows
+  - x64-windows
+
+configuration:
+  - Debug
+  - Release
+
+for:
+  -
+    matrix:
+      only:
+        - configuration: Debug
+          platform: x86-windows
+          compiler: clang
+    environment:
+      CC: clang-cl
+      CXX: clang-cl
+      CFLAGS: -Og -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -m32
+      CXXFLAGS: -Og -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -m32
+    build_script:
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Debug -GNinja
+      - cmake --build .
+
+  -
+    matrix:
+      only:
+        - configuration: Release
+          platform: x86-windows
+          compiler: clang
+    environment:
+      CC: clang-cl
+      CXX: clang-cl
+      CFLAGS: -O2 -m32
+      CXXFLAGS: -O2 -m32
+    build_script:
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -GNinja
+      - cmake --build .
+
+  -
+    matrix:
+      only:
+        - configuration: Debug
+          platform: x86-windows
+          compiler: msvc
+    build_script:
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -AWin32
+      - cmake --build . --config Debug
+
+  -
+    matrix:
+      only:
+        - configuration: Release
+          platform: x86-windows
+          compiler: msvc
+    build_script:
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -AWin32
+      - cmake --build . --config Release
+
+  -
+    matrix:
+      only:
+        - configuration: Debug
+          platform: x86-windows
+          compiler: gcc
+    environment:
+      CC: gcc
+      CXX: g++
+      CFLAGS: -Og -g -Wall -Wextra
+      CXXFLAGS: -Og -g -Wall -Wextra
+    build_script:
+      - SET PATH=C:\\mingw-w64\\i686-8.1.0-posix-dwarf-rt_v6-rev0\\mingw32\\bin;%PATH%
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Debug -G"MinGW Makefiles"
+      - cmake --build .
+
+  -
+    matrix:
+      only:
+        - configuration: Release
+          platform: x86-windows
+          compiler: gcc
+    environment:
+      CC: gcc
+      CXX: g++
+      CFLAGS: -O2
+      CXXFLAGS: -O2
+    build_script:
+      - SET PATH=C:\\mingw-w64\\i686-8.1.0-posix-dwarf-rt_v6-rev0\\mingw32\\bin;%PATH%
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -G"MinGW Makefiles"
+      - cmake --build .
+
+  -
+    matrix:
+      only:
+        - configuration: Debug
+          platform: x64-windows
+          compiler: clang
+    environment:
+      CC: clang-cl
+      CXX: clang-cl
+      CFLAGS: -Og -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic
+      CXXFLAGS: -Og -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic
+    build_script:
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Debug -GNinja
+      - cmake --build .
+
+  -
+    matrix:
+      only:
+        - configuration: Release
+          platform: x64-windows
+          compiler: clang
+    environment:
+      CC: clang-cl
+      CXX: clang-cl
+      CFLAGS: -O2
+      CXXFLAGS: -O2
+    build_script:
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -GNinja
+      - cmake --build .
+
+  -
+    matrix:
+      only:
+        - configuration: Debug
+          platform: x64-windows
+          compiler: msvc
+    build_script:
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -Ax64
+      - cmake --build . --config Debug
+
+  -
+    matrix:
+      only:
+        - configuration: Release
+          platform: x64-windows
+          compiler: msvc
+    build_script:
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -Ax64
+      - cmake --build . --config Release
+
+  -
+    matrix:
+      only:
+        - configuration: Debug
+          platform: x64-windows
+          compiler: gcc
+    environment:
+      CC: gcc
+      CXX: g++
+      CFLAGS: -Og -g -Wall -Wextra
+      CXXFLAGS: -Og -g -Wall -Wextra
+    build_script:
+      - SET PATH=C:\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin;%PATH%
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Debug -G"MinGW Makefiles"
+      - cmake --build .
+
+  -
+    matrix:
+      only:
+        - configuration: Release
+          platform: x64-windows
+          compiler: gcc
+    environment:
+      CC: gcc
+      CXX: g++
+      CFLAGS: -O2
+      CXXFLAGS: -O2
+    build_script:
+      - SET PATH=C:\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin;%PATH%
+      - call "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
+      - cmake .. -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -G"MinGW Makefiles"
+      - cmake --build .
+
+before_build:
+  - cd %APPVEYOR_BUILD_FOLDER%
+  - mkdir build
+  - cd build
+
+install:
+  - cd C:\Tools\vcpkg
+#msys repos are temporary down, downloading two dependencies manuallly from a mirror repo
+  - if not exist downloads mkdir downloads
+  - cd downloads
+  - curl -O https://mirrors.ustc.edu.cn/msys2/mingw/i686/mingw-w64-i686-pkg-config-0.29.2-1-any.pkg.tar.xz
+  - curl -O https://mirrors.ustc.edu.cn/msys2/mingw/i686/mingw-w64-i686-libwinpthread-git-8.0.0.5906.c9a21571-1-any.pkg.tar.zst
+  - cd ..
+#end of the hotfix
+  - vcpkg install zlib:%platform% openssl:%platform%
+  - cd %APPVEYOR_BUILD_FOLDER%
+
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..344a864
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+charset = utf-8
+trim_trailing_whitespace = true
+end_of_line = lf
+insert_final_newline = true
+
+# Tab indentation (no size specified)
+[Makefile]
+indent_style = tab
+
+[*.{c,h,cpp,hpp}]
+indent_size = 2
diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml
new file mode 100644
index 0000000..5560454
--- /dev/null
+++ b/.github/workflows/cmake.yml
@@ -0,0 +1,38 @@
+name: CMake
+
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+env:
+  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
+  BUILD_TYPE: Release
+
+jobs:
+  build:
+    # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
+    # You can convert this to a matrix build if you need cross-platform coverage.
+    # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+
+    - name: Configure CMake
+      # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
+      # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
+      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+
+    - name: Build
+      # Build your program with the given configuration
+      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+
+    - name: Test
+      working-directory: ${{github.workspace}}/build
+      # Execute tests defined by the CMake configuration.  
+      # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
+      run: ctest -C ${{env.BUILD_TYPE}}
+      # FIXME
+      continue-on-error: true
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000..557e447
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,71 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+name: "CodeQL"
+
+on:
+  push:
+    branches: [master]
+  pull_request:
+    # The branches below must be a subset of the branches above
+    branches: [master]
+  schedule:
+    - cron: '0 1 * * 3'
+
+jobs:
+  analyze:
+    name: Analyze
+    runs-on: ubuntu-latest
+
+    strategy:
+      fail-fast: false
+      matrix:
+        # Override automatic language detection by changing the below list
+        # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
+        language: ['cpp']
+        # Learn more...
+        # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
+
+    steps:
+    - name: Checkout repository
+      uses: actions/checkout@v2
+      with:
+        # We must fetch at least the immediate parents so that if this is
+        # a pull request then we can checkout the head.
+        fetch-depth: 2
+
+    # If this run was triggered by a pull request event, then checkout
+    # the head of the pull request instead of the merge commit.
+    - run: git checkout HEAD^2
+      if: ${{ github.event_name == 'pull_request' }}
+
+    # Initializes the CodeQL tools for scanning.
+    - name: Initialize CodeQL
+      uses: github/codeql-action/init@v1
+      with:
+        languages: ${{ matrix.language }}
+        # If you wish to specify custom queries, you can do so here or in a config file.
+        # By default, queries listed here will override any specified in a config file. 
+        # Prefix the list here with "+" to use these queries and those in the config file.
+        # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
+    # If this step fails, then you should remove it and run the build manually (see below)
+    - name: Autobuild
+      uses: github/codeql-action/autobuild@v1
+
+    # ℹ️ Command-line programs to run using the OS shell.
+    # 📚 https://git.io/JvXDl
+
+    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+    #    and modify them (or add more) to build your code if your project
+    #    uses a compiled language
+
+    #- run: |
+    #   make bootstrap
+    #   make release
+
+    - name: Perform CodeQL Analysis
+      uses: github/codeql-action/analyze@v1
diff --git a/.gitignore b/.gitignore
index 38bafce..630a4e6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,4 @@ src/unshield-deobfuscate
 .*.swp
 .idea
 build
+/cmake-build-debug/
diff --git a/.travis.yml b/.travis.yml
index 9c5d191..ccaf373 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,10 @@
+os:
+  - linux
+  - osx
+
+osx_image: xcode12u
+dist: bionic
+
 language: c
 
 compiler:
@@ -12,7 +19,37 @@ env:
     - USE_OUR_OWN_MD5=1 BUILD_STATIC=0
     - USE_OUR_OWN_MD5=0 BUILD_STATIC=1
     - USE_OUR_OWN_MD5=1 BUILD_STATIC=1
+    - STATIC_ANALYZER=scan-build CMAKE_OPTS="-DCMAKE_BUILD_TYPE=Debug"
+
+addons:
+  apt:
+    packages:
+      - clang
+  homebrew:
+    packages:
+      - openssl
+      - gcc@10
+
+matrix:
+  exclude:
+    - os: osx
+      env: STATIC_ANALYZER=scan-build CMAKE_OPTS="-DCMAKE_BUILD_TYPE=Debug"
+  allow_failures:
+    - env: USE_OUR_OWN_MD5=1 BUILD_STATIC=0
+    - env: STATIC_ANALYZER=scan-build CMAKE_OPTS="-DCMAKE_BUILD_TYPE=Debug"
+
+install:
+  # Help CMake find OpenSSL
+  - if [ "$TRAVIS_OS_NAME" = "osx" ]; then export CMAKE_OPTS="-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl"; fi
+  # Use the real gcc, not clang
+  - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$CC" = "gcc" ]; then CC=gcc-10; $CC --version; fi
 
 # cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/var/tmp/unshield . && make && make install
-script: mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=/var/tmp/unshield -DUSE_OUR_OWN_MD5=$USE_OUR_OWN_MD5 -DBUILD_STATIC=$BUILD_STATIC .. && make && make install && ../run-tests.sh
+script:
+  - mkdir build
+  - cd build
+  - $STATIC_ANALYZER cmake -DCMAKE_INSTALL_PREFIX:PATH=/var/tmp/unshield -DUSE_OUR_OWN_MD5=$USE_OUR_OWN_MD5 -DBUILD_STATIC=$BUILD_STATIC ${CMAKE_OPTS:-} ..
+  - $STATIC_ANALYZER make
+  - make install
+  - ../run-tests.sh
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 39ae378..3a25225 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,15 +1,16 @@
 cmake_minimum_required(VERSION 2.8.7)
-project(unshield)
+project(unshield C)
 
 # Mimic CMP0048 which is avaliable only for cmake 3.0 and later
 set(PROJECT_VERSION_MAJOR 1)
-set(PROJECT_VERSION_MINOR 4)
-set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
+set(PROJECT_VERSION_MINOR 5)
+set(PROJECT_VERSION_PATCH 1)
+set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
 
 option(BUILD_STATIC "Build static version of libunshield" OFF)
 
 include(CheckIncludeFiles)
-include(CheckFunctionExists)
+include(CheckSymbolExists)
 include(CheckCSourceCompiles)
 include(GNUInstallDirs)
 
@@ -26,8 +27,8 @@ check_include_files(sys/byteswap.h HAVE_SYS_BYTESWAP_H)
 check_include_files(sys/stat.h HAVE_SYS_STAT_H)
 check_include_files(sys/types.h HAVE_SYS_TYPES_H)
 check_include_files(unistd.h HAVE_UNISTD_H)
-check_function_exists(fnmatch HAVE_FNMATCH)
-check_function_exists(iconv HAVE_ICONV)
+check_symbol_exists(fnmatch fnmatch.h HAVE_FNMATCH)
+check_symbol_exists(iconv iconv.h HAVE_ICONV)
 
 set(SIZE_FORMAT "zi")
 check_c_source_compiles("#include <stdio.h>\nint main(int argc, char **argv) { size_t value = 0; printf(\"%${SIZE_FORMAT}\", value); return 0; }" SIZE_FORMAT_ZI)
@@ -62,14 +63,24 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libunshield.pc.in ${CMAKE_CURRENT_BIN
 include_directories(${CMAKE_CURRENT_BINARY_DIR})
 include_directories(${CMAKE_CURRENT_BINARY_DIR}/lib)
 
-# The POSITION_INDEPENDENT_CODE property was introduced in cmake 2.8.10/CMP0018
-# as we are targeting cmake 2.8.7, we can't use
-#  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-# let's fall back to add_definitions for now
-add_definitions(-fPIC)
+# Function to change MSVC runtime linkage to static
+function(set_msvc_runtime_static)
+    foreach(flag_var
+        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+        if(${flag_var} MATCHES "/MD")
+            string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+        endif()
+    endforeach()
+endfunction()
+
+if (MSVC)
+    add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+    include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32_msvc)
+endif ()
 
 add_subdirectory(lib)
 add_subdirectory(src)
 
-install(FILES man/unshield.1 DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/man/man1)
+install(FILES man/unshield.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libunshield.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
diff --git a/README.md b/README.md
index a64e96b..cae426d 100644
--- a/README.md
+++ b/README.md
@@ -2,13 +2,22 @@ Unshield
 ========
 
 [![Build Status](https://travis-ci.org/twogood/unshield.png?branch=master)](https://travis-ci.org/twogood/unshield)
+[![Packaging status](https://repology.org/badge/tiny-repos/unshield.svg)](https://repology.org/project/unshield/versions)
+[![Homebrew package](https://repology.org/badge/version-for-repo/homebrew/unshield.svg)](https://repology.org/project/unshield/versions)
+
+
+#### Microsoft Windows build
+[![Appveyor Build status](https://ci.appveyor.com/api/projects/status/rnjlecanres5au3q?svg=true)](https://ci.appveyor.com/project/twogood/unshield)
+
+[Download page](https://ci.appveyor.com/project/twogood/unshield/build/artifacts)
+
+Note: The Microsoft Windows build is currently broken even if Appveyor doesn't notice, sorry about that! A PR to fix this is welcome!
 
 
 Support Unshield development
 ----------------------------
 
 - [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SQ7PEFMJK36AU)
-- [Pledgie](https://pledgie.com/campaigns/29872)
 
 
 Dictionary
@@ -82,4 +91,13 @@ like, but don't blame me if anything goes wrong".
 See the file LICENSE for details.
 
 
+Build From Source
+-----------------
+
+Just use the standard CMake build process:
 
+``` sh
+cmake .
+make
+make install
+```
diff --git a/debian/changelog b/debian/changelog
index fe3797e..e67fd5c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+unshield (1.5.1-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Sat, 19 Mar 2022 06:01:44 -0000
+
 unshield (1.4.2-1) unstable; urgency=medium
 
   * New upstream version 1.4.2
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 18e17cf..2a4b475 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -1,3 +1,7 @@
+cmake_minimum_required(VERSION 3.6)
+
+project(libunshield C)
+
 add_subdirectory(convert_utf)
 
 if(USE_OUR_OWN_MD5)
@@ -23,21 +27,21 @@ set(LIBUNSHIELD_SOURCES
 )
 
 if(BUILD_STATIC)
-    set(LIBUNSHIELD_LIBRARY_TYPE STATIC)
+    add_library(${PROJECT_NAME} STATIC ${LIBUNSHIELD_HEADES} ${LIBUNSHIELD_SOURCES})
 else()
-    set(LIBUNSHIELD_LIBRARY_TYPE SHARED)
+    add_library(${PROJECT_NAME} SHARED ${LIBUNSHIELD_HEADES} ${LIBUNSHIELD_SOURCES})
 endif()
 
-add_library(libunshield ${LIBUNSHIELD_LIBRARY_TYPE} ${LIBUNSHIELD_HEADES} ${LIBUNSHIELD_SOURCES})
+target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(${PROJECT_NAME} PUBLIC ZLIB::ZLIB convert_utf)
+set_target_properties(libunshield PROPERTIES OUTPUT_NAME unshield)
+set_target_properties(libunshield PROPERTIES VERSION 0.0.0 SOVERSION 0)
 
 if(USE_OUR_OWN_MD5)
-    target_link_libraries(libunshield ${ZLIB_LIBRARY} md5 convert_utf)
+    target_link_libraries(${PROJECT_NAME} PUBLIC md5)
 else()
-    target_link_libraries(libunshield ${ZLIB_LIBRARY} ${OPENSSL_LIBRARIES} convert_utf)
+    target_link_libraries(${PROJECT_NAME} PUBLIC OpenSSL::Crypto)
 endif()
 
-set_target_properties(libunshield PROPERTIES OUTPUT_NAME unshield)
-set_target_properties(libunshield PROPERTIES VERSION 0.0.0 SOVERSION 0)
-
 install(TARGETS libunshield RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
-install(FILES libunshield.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
\ No newline at end of file
+install(FILES libunshield.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
diff --git a/lib/cabfile.h b/lib/cabfile.h
index 32ce2b4..4f52cfe 100644
--- a/lib/cabfile.h
+++ b/lib/cabfile.h
@@ -2,8 +2,6 @@
 #ifndef __cabfile_h__
 #define __cabfile_h__
 
-#include "internal.h"
-
 #define OFFSET_COUNT 0x47
 #define CAB_SIGNATURE 0x28635349
 
@@ -60,10 +58,10 @@ typedef struct
   uint32_t component_offsets [MAX_COMPONENT_COUNT];   /* 0x15a */
 } CabDescriptor;
 
-#define FILE_SPLIT			  1
-#define FILE_OBFUSCATED   2
-#define FILE_COMPRESSED		4
-#define FILE_INVALID		  8
+#define FILE_SPLIT			  1U
+#define FILE_OBFUSCATED   2U
+#define FILE_COMPRESSED		4U
+#define FILE_INVALID		  8U
 
 #define LINK_NONE	0
 #define LINK_PREV	1
@@ -75,9 +73,9 @@ typedef struct
   uint32_t name_offset;
   uint32_t directory_index;
   uint16_t flags;
-  uint32_t expanded_size;
-  uint32_t compressed_size;
-  uint32_t data_offset;
+  uint64_t expanded_size;
+  uint64_t compressed_size;
+  uint64_t data_offset;
   uint8_t md5[16];
   uint16_t volume;
   uint32_t link_previous;
diff --git a/lib/convert_utf/CMakeLists.txt b/lib/convert_utf/CMakeLists.txt
index 4b956e9..6a66530 100644
--- a/lib/convert_utf/CMakeLists.txt
+++ b/lib/convert_utf/CMakeLists.txt
@@ -6,4 +6,17 @@ set(LIBCONVERT_UTF_SOURCES
     "ConvertUTF.c"
 )
 
+if(BUILD_STATIC AND MSVC)
+    set_msvc_runtime_static()
+endif()
+
 add_library(convert_utf STATIC ${LIBCONVERT_UTF_HEADES} ${LIBCONVERT_UTF_SOURCES})
+
+# Linux/Clang-7
+# relocation R_X86_64_32S against `.rodata' can not be used when making a shared object;
+# recompile with -fPIC
+include(CheckCCompilerFlag)
+CHECK_C_COMPILER_FLAG("-fPIC" COMPILER_HAS_FPIC)
+if (COMPILER_HAS_FPIC)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+endif()
diff --git a/lib/file.c b/lib/file.c
index 2dc7969..9e4f15f 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -14,10 +14,20 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
+
+#if !defined(_MSC_VER)
 #include <sys/param.h>    /* for MIN(a,b) */
+#endif
+
+#ifdef _WIN32
+#define fseek _fseeki64
+#define ftell _ftelli64
+#endif
+
 #ifndef MIN /* missing in some platforms */
 #define MIN(a,b) (((a)<(b))?(a):(b))
 #endif
+
 #include <zlib.h>
 
 #define VERBOSE 3
@@ -25,6 +35,7 @@
 #define ror8(x,n)   (((x) >> ((int)(n))) | ((x) << (8 - (int)(n))))
 #define rol8(x,n)   (((x) << ((int)(n))) | ((x) >> (8 - (int)(n))))
 
+static const uint8_t END_OF_CHUNK[4] = { 0x00, 0x00, 0xff, 0xff };
 
 static FileDescriptor* unshield_read_file_descriptor(Unshield* unshield, int index)
 {
@@ -95,12 +106,9 @@ static FileDescriptor* unshield_read_file_descriptor(Unshield* unshield, int ind
       unshield_trace("File descriptor offset: %08x", p - header->data);
 #endif
       fd->flags             = READ_UINT16(p); p += 2;
-      fd->expanded_size     = READ_UINT32(p); p += 4;
-      p += 4;
-      fd->compressed_size   = READ_UINT32(p); p += 4;
-      p += 4;
-      fd->data_offset       = READ_UINT32(p); p += 4;
-      p += 4;
+      fd->expanded_size     = READ_UINT64(p); p += 8;
+      fd->compressed_size   = READ_UINT64(p); p += 8;
+      fd->data_offset       = READ_UINT64(p); p += 8;
       memcpy(fd->md5, p, 0x10); p += 0x10;
       p += 0x10;
       fd->name_offset       = READ_UINT32(p); p += 4;
@@ -302,9 +310,9 @@ typedef struct
 static bool unshield_reader_open_volume(UnshieldReader* reader, int volume)/*{{{*/
 {
   bool success = false;
-  unsigned data_offset = 0;
-  unsigned volume_bytes_left_compressed;
-  unsigned volume_bytes_left_expanded;
+  uint64_t data_offset = 0;
+  uint64_t volume_bytes_left_compressed;
+  uint64_t volume_bytes_left_expanded;
   CommonHeader common_header;
 
 #if VERBOSE >= 2
@@ -579,6 +587,92 @@ exit:
   return success;
 }/*}}}*/
 
+int copy_file(FILE* infile, FILE* outfile) {
+#define SIZE (1024*1024)
+
+    char buffer[SIZE];
+    size_t bytes;
+
+    while (0 < (bytes = fread(buffer, 1, sizeof(buffer), infile)))
+        fwrite(buffer, 1, bytes, outfile);
+
+    return 0;
+}
+
+
+static UnshieldReader* unshield_reader_create_external(/*{{{*/
+        Unshield* unshield,
+        int index,
+        FileDescriptor* file_descriptor)
+{
+    bool success = false;
+    const char* file_name = unshield_file_name(unshield, index);
+    const char* directory_name = unshield_directory_name(unshield, file_descriptor->directory_index);
+    char* base_directory_name = unshield_get_base_directory_name(unshield);
+    long int path_max = unshield_get_path_max(unshield);
+    char* directory_and_filename = malloc(path_max);
+
+    UnshieldReader* reader = NEW1(UnshieldReader);
+    if (!reader)
+        goto exit;
+
+    reader->unshield          = unshield;
+    reader->index             = index;
+    reader->file_descriptor   = file_descriptor;
+
+    snprintf(directory_and_filename, path_max, "%s/%s/%s", base_directory_name, directory_name, file_name);
+
+    reader->volume_file = fopen(directory_and_filename, "rb");
+    if (!reader->volume_file)
+    {
+        unshield_error("Failed to open input file %s", directory_and_filename);
+        goto exit;
+    }
+
+    if (file_descriptor->flags & FILE_COMPRESSED) {
+        long file_size = FSIZE(reader->volume_file);
+        FILE *temporary_file = NULL;
+
+        /*
+         * Normally the compressed data is nicely terminated with end of chunk marker 00 00 ff ff but not always
+         * This seem to happen for small files where the compressed size and expanded size are almost the same.
+         * Workaround: Create a temporary file with the correct end of chunk.
+         */
+
+        long diff = file_descriptor->compressed_size - file_size;
+        if (diff > 0) {
+            diff = MIN(sizeof(END_OF_CHUNK), diff);
+            temporary_file = tmpfile();
+            copy_file(reader->volume_file, temporary_file);
+            fwrite(END_OF_CHUNK + sizeof(END_OF_CHUNK) - diff, 1, diff, temporary_file);
+            fseek(temporary_file, 0, SEEK_SET);
+
+            fclose(reader->volume_file);
+            reader->volume_file = temporary_file;
+
+            reader->volume_bytes_left = file_size + diff;
+        }
+        else {
+            reader->volume_bytes_left = file_descriptor->compressed_size;
+        }
+    }
+    else {
+        reader->volume_bytes_left = file_descriptor->expanded_size;
+    }
+
+    success = true;
+
+exit:
+    FREE(base_directory_name);
+    FREE(directory_and_filename);
+
+    if (success)
+        return reader;
+
+    FREE(reader);
+    return NULL;
+}
+
 static UnshieldReader* unshield_reader_create(/*{{{*/
     Unshield* unshield, 
     int index,
@@ -921,11 +1015,12 @@ bool unshield_file_save_raw(Unshield* unshield, int index, const char* filename)
 
     bytes_left -= bytes_to_write;
 
-    if (bytes_to_write != fwrite(output_buffer, 1, bytes_to_write, output))
-    {
-      unshield_error("Failed to write %i bytes to file '%s'", bytes_to_write, filename);
-      goto exit;
-    }
+      if (output) {
+          if (bytes_to_write != fwrite(output_buffer, 1, bytes_to_write, output)) {
+              unshield_error("Failed to write %i bytes to file '%s'", bytes_to_write, filename);
+              goto exit;
+          }
+      }
   }
 
   success = true;
@@ -942,7 +1037,7 @@ static uint8_t* find_bytes(
     const uint8_t* buffer, size_t bufferSize, 
     const uint8_t* pattern, size_t patternSize)
 {
-  const void *p = buffer;
+  const unsigned char *p = buffer;
   size_t buffer_left = bufferSize;
   while ((p = memchr(p, pattern[0], buffer_left)) != NULL)
   {
@@ -1002,8 +1097,14 @@ bool unshield_file_save_old(Unshield* unshield, int index, const char* filename)
 
   if (unshield_fsize(reader->volume_file) == (long)file_descriptor->data_offset)
   {
-    unshield_error("File %i is not inside the cabinet.", index);
-    goto exit;
+      unshield_error("File %i is not inside the cabinet. Trying external file!", index);
+      unshield_reader_destroy(reader);
+      reader = unshield_reader_create_external(unshield, index, file_descriptor);
+      if (!reader)
+      {
+          unshield_error("Failed to create data reader for file %i", index);
+          goto exit;
+      }
   }
 
   if (filename) 
@@ -1016,12 +1117,11 @@ bool unshield_file_save_old(Unshield* unshield, int index, const char* filename)
     }
   }
 
-  if (file_descriptor->flags & FILE_COMPRESSED)
-    bytes_left = file_descriptor->compressed_size;
-  else
     bytes_left = file_descriptor->expanded_size;
 
-  /*unshield_trace("Bytes to read: %i", bytes_left);*/
+#if VERBOSE >= 4
+  unshield_trace("Bytes to write: %i", bytes_left);
+#endif
 
   while (bytes_left > 0)
   {
@@ -1037,7 +1137,6 @@ bool unshield_file_save_old(Unshield* unshield, int index, const char* filename)
 
     if (file_descriptor->flags & FILE_COMPRESSED)
     {
-      static const uint8_t END_OF_CHUNK[4] = { 0x00, 0x00, 0xff, 0xff };
       uLong read_bytes;
       size_t input_size = reader->volume_bytes_left;
       uint8_t* chunk_buffer;
@@ -1062,15 +1161,13 @@ bool unshield_file_save_old(Unshield* unshield, int index, const char* filename)
         goto exit;
       }
 
-      bytes_left -= input_size;
-
-      for (chunk_buffer = input_buffer; input_size; )
+      for (chunk_buffer = input_buffer; input_size && bytes_left; )
       {
         size_t chunk_size;
         uint8_t* match = find_bytes(chunk_buffer, input_size, END_OF_CHUNK, sizeof(END_OF_CHUNK));
         if (!match)
         {
-          unshield_error("Could not find end of chunk for file %i (%s) from input cabinet file %i", 
+          unshield_error("Could not find end of chunk for file %i (%s) from input cabinet file %i",
               index, unshield_file_name(unshield, index), file_descriptor->volume);
           goto exit;
         }
@@ -1132,11 +1229,13 @@ bool unshield_file_save_old(Unshield* unshield, int index, const char* filename)
         input_size -= chunk_size;
         input_size -= sizeof(END_OF_CHUNK);
 
-        if (output)
-          if (bytes_to_write != fwrite(output_buffer, 1, bytes_to_write, output))
-          {
-            unshield_error("Failed to write %i bytes to file '%s'", bytes_to_write, filename);
-            goto exit;
+          bytes_left -= bytes_to_write;
+
+          if (output) {
+              if (bytes_to_write != fwrite(output_buffer, 1, bytes_to_write, output)) {
+                  unshield_error("Failed to write %i bytes to file '%s'", bytes_to_write, filename);
+                  goto exit;
+              }
           }
 
         total_written += bytes_to_write;
@@ -1157,14 +1256,16 @@ bool unshield_file_save_old(Unshield* unshield, int index, const char* filename)
 
       bytes_left -= bytes_to_write;
 
-      if (output)
+      if (output) {
         if (bytes_to_write != fwrite(output_buffer, 1, bytes_to_write, output))
         {
           unshield_error("Failed to write %i bytes to file '%s'", bytes_to_write, filename);
           goto exit;
         }
+      }
 
       total_written += bytes_to_write;
+
     }
   }
 
diff --git a/lib/file_group.c b/lib/file_group.c
index e11cba5..02091d9 100644
--- a/lib/file_group.c
+++ b/lib/file_group.c
@@ -17,7 +17,7 @@ UnshieldFileGroup* unshield_file_group_new(Header* header, uint32_t offset)/*{{{
 
   self->name = unshield_header_get_string(header, READ_UINT32(p)); p += 4;
 
-  if (header->major_version == 5)
+  if (header->major_version <= 5)
     p += 0x48;
   else
     p += 0x12;
diff --git a/lib/helper.c b/lib/helper.c
index 0c61bbe..3d5d86f 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -11,6 +11,8 @@
 #include <unistd.h>
 
 #ifdef _WIN32
+  #define fseek _fseeki64
+  #define ftell _ftelli64
   #define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
   #include <direct.h>
   #ifndef PATH_MAX
@@ -22,60 +24,85 @@
 
 #define VERBOSE 0
 
+#if defined(_MSC_VER)
+  #define snprintf _snprintf
+  #define vsnprintf _vsnprintf
+  #define strcasecmp _stricmp
+  #define strncasecmp _strnicmp
+#endif
+
+long int unshield_get_path_max(Unshield* unshield)
+{
+#ifdef PATH_MAX
+    return PATH_MAX;
+#else
+    long int path_max = pathconf(unshield->filename_pattern, _PC_PATH_MAX);
+    if (path_max <= 0)
+      path_max = 4096;
+    return path_max;
+#endif
+}
+
+char *unshield_get_base_directory_name(Unshield *unshield) {
+    long int path_max = unshield_get_path_max(unshield);
+    char *p = strrchr(unshield->filename_pattern, '/');
+    char *dirname = malloc(path_max);
+
+    if (p) {
+        strncpy(dirname, unshield->filename_pattern, path_max);
+        if ((unsigned int) (p - unshield->filename_pattern) > path_max) {
+            dirname[path_max - 1] = 0;
+        } else
+            dirname[(p - unshield->filename_pattern)] = 0;
+    } else
+        strcpy(dirname, ".");
+
+    return dirname;
+}
+
+
+static char* get_filename(Unshield* unshield, int index, const char* suffix) {
+    if (unshield && unshield->filename_pattern)
+    {
+        long path_max = unshield_get_path_max(unshield);
+        char* filename  = malloc(path_max);
+
+        if (filename == NULL) {
+            unshield_error("Unable to allocate memory.\n");
+            goto exit;
+        }
+
+        if (snprintf(filename, path_max, unshield->filename_pattern, index, suffix) >= path_max) {
+            unshield_error("Pathname exceeds system limits.\n");
+            goto exit;
+        }
+
+    exit:
+        return filename;
+    }
+
+    return NULL;
+}
+
+
 FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suffix)
 {
   if (unshield && unshield->filename_pattern)
   {
     FILE* result = NULL;
-    char* filename = NULL;
-    char* dirname = NULL;
-    char * p = strrchr(unshield->filename_pattern, '/');
+    char* filename = get_filename(unshield, index, suffix);
+    char* dirname = unshield_get_base_directory_name(unshield);
     const char *q;
     struct dirent *dent = NULL;
     DIR *sourcedir = NULL;
-    long int path_max;
-
-    #ifdef PATH_MAX
-    path_max = PATH_MAX;
-    #else
-    path_max = pathconf(unshield->filename_pattern, _PC_PATH_MAX);
-    if (path_max <= 0)
-      path_max = 4096;
-    #endif
-
-    dirname = malloc(path_max);
-    filename = malloc(path_max);
-    if (filename == NULL || dirname == NULL)
-    {
-      unshield_error("Unable to allocate memory.\n");
-      goto exit;
-    }
+    long int path_max = unshield_get_path_max(unshield);
 
-    if(snprintf(filename, path_max, unshield->filename_pattern, index, suffix)>=path_max)
-    {
-      unshield_error("Pathname exceeds system limits.\n");
-      goto exit;
-    }
     q=strrchr(filename,'/');
     if (q)
       q++;
     else
       q=filename;
 
-    if (p)
-    {
-      strncpy( dirname, unshield->filename_pattern,path_max);
-      if ((unsigned int)(p-unshield->filename_pattern) > path_max)
-      {
-        unshield_trace("WARN: size\n");
-        dirname[path_max-1]=0;
-      }
-      else
-        dirname[(p-unshield->filename_pattern)] = 0;
-    }
-    else
-      strcpy(dirname,".");
-
     sourcedir = opendir(dirname);
     /* Search for the File case independent */
     if (sourcedir)
@@ -120,10 +147,10 @@ exit:
   return NULL;
 }
 
-long unshield_fsize(FILE* file)
+long long unshield_fsize(FILE* file)
 {
-  long result;
-  long previous = ftell(file);
+  long long result;
+  long long previous = ftell(file);
   fseek(file, 0L, SEEK_END);
   result = ftell(file);
   fseek(file, previous, SEEK_SET);
@@ -140,7 +167,7 @@ bool unshield_read_common_header(uint8_t** buffer, CommonHeader* common)
     unshield_error("Invalid file signature");
 
     if (MSCF_SIGNATURE == common->signature)
-      unshield_warning("Found Microsoft Cabinet header. Use cabextract (http://www.kyz.uklinux.net/cabextract.php) to unpack this file.");
+      unshield_warning("Found Microsoft Cabinet header. Use cabextract (https://www.cabextract.org.uk/) to unpack this file.");
 
     return false;
   }
@@ -198,7 +225,7 @@ static const char* unshield_utf16_to_utf8(Header* header, const uint16_t* utf16)
 {
   StringBuffer* string_buffer = unshield_add_string_buffer(header); 
   int length = unshield_strlen_utf16(utf16);
-  int buffer_size = 2 * length + 1;
+  int buffer_size = 3 * length + 1;
   char* target = string_buffer->string = NEW(char, buffer_size);
   ConversionResult result = ConvertUTF16toUTF8(
       (const UTF16**)&utf16, utf16 + length + 1, 
diff --git a/lib/internal.h b/lib/internal.h
index 1f5718a..f2de0f5 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -75,8 +75,10 @@ void unshield_file_group_destroy(UnshieldFileGroup* self);
    Helpers
  */
 
+char *unshield_get_base_directory_name(Unshield *unshield);
+long int unshield_get_path_max(Unshield* unshield);
 FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suffix);
-long unshield_fsize(FILE* file);
+long long unshield_fsize(FILE* file);
 bool unshield_read_common_header(uint8_t** buffer, CommonHeader* common);
 
 const char* unshield_get_utf8_string(Header* header, const void* buffer);
@@ -95,12 +97,12 @@ uint8_t* unshield_header_get_buffer(Header* header, uint32_t offset);
    Macros for safer development
  */
 
-#define FREE(ptr)       { if (ptr) { free(ptr); ptr = NULL; } }
+#define FREE(ptr)       { if (ptr) { free(ptr); (ptr) = NULL; } }
 #define STRDUP(str)     ((str) ? strdup(str) : NULL)
 #define NEW(type, count)      ((type*)calloc(count, sizeof(type)))
 #define NEW1(type)      ((type*)calloc(1, sizeof(type)))
-#define FCLOSE(file)    if (file) { fclose(file); file = NULL; }
-#define FSIZE(file)     (file ? unshield_fsize(file) : 0)
+#define FCLOSE(file)    if (file) { fclose(file); (file) = NULL; }
+#define FSIZE(file)     ((file) ? unshield_fsize(file) : 0)
 #define STREQ(s1,s2)    (0 == strcmp(s1,s2))
 
 #if WORDS_BIGENDIAN
@@ -138,8 +140,14 @@ static inline uint32_t get_unaligned_le32(const uint8_t *p)
     return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
 }
 
+static inline uint64_t get_unaligned_le64(const uint8_t *p)
+{
+    return (uint64_t)get_unaligned_le32(p + 4) << 32 | get_unaligned_le32(p);
+}
+
 #define READ_UINT16(p)   get_unaligned_le16(p)
 #define READ_UINT32(p)   get_unaligned_le32(p)
+#define READ_UINT64(p)   get_unaligned_le64(p)
 
 #define READ_INT16(p)   ((int16_t)READ_UINT16(p))
 #define READ_INT32(p)   ((int32_t)READ_UINT32(p))
diff --git a/lib/log.h b/lib/log.h
index 37995dc..49641df 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -19,18 +19,14 @@ extern "C"
 
 void _unshield_log(int level, const char* file, int line, const char* format, ...);
 
-#define unshield_trace(format, args...) \
-	_unshield_log(UNSHIELD_LOG_LEVEL_TRACE,__FUNCTION__, __LINE__, format, ##args)
+#define unshield_trace(format, ...) \
+	_unshield_log(UNSHIELD_LOG_LEVEL_TRACE,__FUNCTION__, __LINE__, format, ##__VA_ARGS__)
 
-#define unshield_warning(format, args...) \
-	_unshield_log(UNSHIELD_LOG_LEVEL_WARNING,__FUNCTION__, __LINE__, format, ##args)
+#define unshield_warning(format, ...) \
+	_unshield_log(UNSHIELD_LOG_LEVEL_WARNING,__FUNCTION__, __LINE__, format, ##__VA_ARGS__)
 
-#define unshield_warning_unless(cond, format, args...) \
-	if (!(cond)) \
-	_unshield_log(UNSHIELD_LOG_LEVEL_WARNING,__FUNCTION__, __LINE__, format, ##args)
-
-#define unshield_error(format, args...) \
-	_unshield_log(UNSHIELD_LOG_LEVEL_ERROR,__FUNCTION__, __LINE__, format, ##args)
+#define unshield_error(format, ...) \
+	_unshield_log(UNSHIELD_LOG_LEVEL_ERROR,__FUNCTION__, __LINE__, format, ##__VA_ARGS__)
 
 #ifdef __cplusplus
 }
diff --git a/lib/md5/CMakeLists.txt b/lib/md5/CMakeLists.txt
index e5b66d6..1986b24 100644
--- a/lib/md5/CMakeLists.txt
+++ b/lib/md5/CMakeLists.txt
@@ -7,4 +7,8 @@ set(LIBMD5_UTF_SOURCES
     "md5c.c"
 )
 
+if(BUILD_STATIC AND MSVC)
+    set_msvc_runtime_static()
+endif()
+
 add_library(md5 STATIC ${LIBMD5_UTF_HEADES} ${LIBMD5_UTF_SOURCES})
diff --git a/man/unshield.1 b/man/unshield.1
index 3b6abd2..94ca5eb 100644
--- a/man/unshield.1
+++ b/man/unshield.1
@@ -2,7 +2,7 @@
 .SH NAME
 unshield \- extract CAB files from an InstallShield installer archive
 .SH SYNOPSIS
-unshield [\-c COMPONENT] [\-d DIRECTORY] [\-D LEVEL] [\-g GROUP] [\-h] [\-j] [\-L] [\-n] [\-o] [\-O] [\-r] [\-v] [\-V] c|g|l|t|x CABFILE
+unshield [\-c COMPONENT] [\-d DIRECTORY] [\-D LEVEL] [\-g GROUP] [\-h] [\-i VERSION] [\-j] [\-L] [\-n] [\-o] [\-O] [\-r] [\-v] [\-V] c|g|l|t|x CABFILE
 .SH DESCRIPTION
 Unshield extracts CAB files from InstallShield installers, used to 
 install software on Microsoft Windows based machines.
@@ -27,6 +27,11 @@ Only list/extract this file group
 \fB\-h\fR
 Show help message
 .TP
+\fB\-i\fR VERSION
+Force InstallShield version number (don't autodetect)\n
+.br
+Use this option if you have a very old archive (generated with InstallShield <= 4) and / or the automatic detection fails
+.TP
 \fB\-j\fR
 Junk paths (do not make directories)
 .TP
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 08dbb63..a8f1671 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,12 +1,25 @@
 LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
 IF("${isSystemDir}" STREQUAL "-1")
 SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
-ENDIF("${isSystemDir}" STREQUAL "-1")
+endif()
 
 add_executable(unshield "unshield.c")
 target_link_libraries(unshield libunshield)
+if(WIN32)
+    if(HAVE_ICONV)
+        target_link_libraries(unshield iconv)
+    endif()
+    target_link_libraries(unshield ${ZLIB_LIBRARIES})
+endif()
 
 add_executable(unshield-deobfuscate "unshield-deobfuscate.c")
 target_link_libraries(unshield-deobfuscate libunshield)
+if(WIN32)
+    target_link_libraries(unshield-deobfuscate ${ZLIB_LIBRARIES})
+endif()
 
-install(TARGETS unshield RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
\ No newline at end of file
+if(BUILD_STATIC AND MSVC)
+    set_msvc_runtime_static()
+endif()
+
+install(TARGETS unshield RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/src/unshield.c b/src/unshield.c
index d42ac85..4d821b2 100644
--- a/src/unshield.c
+++ b/src/unshield.c
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <getopt.h>
 #include "../lib/libunshield.h"
 #ifdef HAVE_CONFIG_H
 #include "lib/unshield_config.h"
@@ -115,7 +116,7 @@ static bool make_sure_directory_exists(const char* directory)/*{{{*/
 
       if (stat(current, &dir_stat) < 0)
       {
-        #ifdef __MINGW32__
+        #if defined (__MINGW32__) || defined (_WIN32)
         if (_mkdir(current) < 0)
         #else
         if (mkdir(current, 0700) < 0)
@@ -200,7 +201,7 @@ static void show_usage(const char* name)
       "\t-O            Use old compression\n"
       "\t-r            Save raw data (do not decompress)\n"
       "\t-R            Don't do any conversion to file and directory names when extracting.\n"
-      "\t-V            Print copyright and version information\n"
+      "\t-V --version  Print copyright and version information\n"
       "\n"
       "Commands:\n"
       "\tc             List components\n"         
@@ -230,11 +231,17 @@ static bool handle_parameters(
     int argc, 
     char* const argv[])
 {
-	int c;
+    int c;
 
-	while ((c = getopt(argc, argv, "c:d:D:g:hi:e:jLnoOrRV")) != -1)
-	{
-		switch (c)
+    static struct option long_options[] =
+    {
+       { "version", no_argument, NULL, 'V' },
+       { NULL, 0, NULL, 0 }
+    };
+
+    while ((c = getopt_long(argc, argv, "c:d:D:g:hi:e:jLnoOrRV", long_options, NULL)) != -1)
+    {
+    switch (c)
     {
       case 'c':
         component_name = optarg;
@@ -299,7 +306,7 @@ static bool handle_parameters(
         break;
 
       case 'V':
-        printf("Unshield version " VERSION ". Copyright (C) 2003-2013 David Eriksson.\n");
+        printf("Unshield version " VERSION ". MIT License. (C) 2003-2021 David Eriksson.\n");
         exit(0);
         break;
 
@@ -472,7 +479,7 @@ static bool extract_file(Unshield* unshield, const char* prefix, int index)
   }
 
 #ifdef HAVE_ICONV
-  if (!convert_encoding(dirname, sizeof(dirname)))
+  if (!convert_encoding(dirname, path_max))
   {
     success = false;
     goto exit;
@@ -503,13 +510,14 @@ static bool extract_file(Unshield* unshield, const char* prefix, int index)
 
 #ifdef HAVE_ICONV
   if (!convert_encoding(filename + strlen(dirname),
-      sizeof(filename) - strlen(dirname)))
+      path_max - strlen(dirname)))
   {
     success = false;
     goto exit;
   }
 #endif
 
+#ifdef __GLIBC__
   /* use GNU extension to return non-existing files to real_output_directory */
   realpath(output_directory, real_output_directory);
   realpath(filename, real_filename);
@@ -518,11 +526,13 @@ static bool extract_file(Unshield* unshield, const char* prefix, int index)
                                        strlen(real_output_directory)) != 0)
   {
     fprintf(stderr, "\n\nExtraction failed.\n");
+    fprintf(stderr, "Error: %s (%d).\n", strerror(errno), errno);
     fprintf(stderr, "Possible directory traversal attack for: %s\n", filename);
     fprintf(stderr, "To be placed at: %s\n\n", real_filename);
     success = false;
     goto exit;
   }
+#endif
 
   printf("  extracting: %s\n", filename);
   switch (format)
@@ -541,7 +551,7 @@ static bool extract_file(Unshield* unshield, const char* prefix, int index)
 exit:
   if (!success)
   {
-    fprintf(stderr, "Failed to extract file '%s'.%s\n", 
+    fprintf(stderr, "Failed to extract file '%s'.%s\n",
         unshield_file_name(unshield, index),
         (log_level < 3) ? "Run unshield again with -D 3 for more information." : "");
     unlink(filename);
@@ -596,7 +606,19 @@ static bool test_file(Unshield* unshield, int index)
   bool success;
 
   printf("  testing: %s\n", unshield_file_name(unshield, index));
-  success = unshield_file_save(unshield, index, NULL);
+
+    switch (format)
+    {
+        case FORMAT_NEW:
+            success = unshield_file_save(unshield, index, NULL);
+            break;
+        case FORMAT_OLD:
+            success = unshield_file_save_old(unshield, index, NULL);
+            break;
+        case FORMAT_RAW:
+            success = unshield_file_save_raw(unshield, index, NULL);
+            break;
+    }
 
   if (!success)
   {
@@ -712,7 +734,8 @@ static bool do_action(Unshield* unshield, ActionHelper helper)
 
   if (component_name)
   {
-    abort();
+    fprintf(stderr, "This action is not implemented for components, sorry! Patch welcome!\n");
+    return false;
   }
   else if (file_group_name)
   {
diff --git a/test/v0/avigomanager.md5 b/test/v0/avigomanager.md5
index e638873..a6fc7a7 100644
--- a/test/v0/avigomanager.md5
+++ b/test/v0/avigomanager.md5
@@ -1,50 +1,51 @@
-a943ad8f40479fa5cd68afba5787be4f  ./English/Avigo100.pgm
-48c56d5db36b20d0f8644a85d1c33dac  ./English/AvigoMgr.exe
-618341f3e7654c8d5d7e13f17bf433f8  ./English/AvigoToPc.avi
-c3f50ecf458c55ac1157b98f74e6ad0f  ./English/Comctl32.dll
-54584845c6f232a18e4c8f7c59aeca09  ./English/cw3220.dll
-87a2adf125be51cdd5d8d3843e0f0b7e  ./English/Dao2535.tlb
-0aba3f8d3a59754306d75c157e1d2b0a  ./English/dao350.dll
-0be37395a851b1d7aaa7039605ec12c9  ./English/Deu100.alb
-5f854403d1e201a397151610fb9c80dd  ./English/DLGDLL.dll
-72960b3faf8c1845f37d1aac23996e6c  ./English/Download.exe
-cb4848abcb77130f48b8f9e9cf6d8977  ./English/Eng100.alb
-0e206fc4ef4a922c1de3199465ee5955  ./English/English/AvigoMan.cnt
-9095276ff7bdda4dd35b79d76397410c  ./English/English/Avigoman.hlp
-2b212e81224f2bdd608d98fe579c8c4c  ./English/Esp100.alb
-abc3474a2219fe49c2a2bf2f3e764a64  ./English/Financial100.app
-1f17ba903bc00e2694e6338c0e9bd8c3  ./English/Fra100.alb
-df1c526338995596901bcc95ed637f33  ./English/French/AvigoMan.cnt
-7265699e1bbae3022376e4f18f2e52b7  ./English/French/AVIGOMAN.HLP
-64889479798be3d1a682ebd2e1b50452  ./English/German/AvigoMan.cnt
-ec267fd5abb90d373e3b9fe6a5762315  ./English/German/Avigoman.hlp
-15f24a05040bb34765c852942480dc0d  ./English/io_common.dll
-5beb2e7cb566e103480f3f4c3b99f006  ./English/io_error.dll
-b83f81c70983c28252c452fcdce906de  ./English/io_ircomm.dll
-955db4b34095dc7340c82a8e328c4aa3  ./English/io_obex.dll
-989c75747c7b24caacf2e4df0330f45c  ./English/io_tiobex.dll
-e21adacb76cfff3350a3e82c4f883a44  ./English/Ita100.alb
-85cf12ce9899c7242233a340dcb10de4  ./English/Italian/AvigoMan.cnt
-048fa624c7f7f9ddf76898f1dd5a5418  ./English/Italian/AVIGOMAN.HLP
-4aec6b69fd4237a2a0562974e55537ef  ./English/language.lng
-8a7871c9b80a678813ca668338432456  ./English/msexcl35.dll
-e8a31571e9b0f79bc30ad7b8afa75c08  ./English/msjet35.dll
-8472c0e32802199891d76d57879bd9d9  ./English/msjint35.dll
-5773425a2bb778684b57d042a0cd5247  ./English/msjter35.dll
-6252deb3dab5e502fcab24183c642563  ./English/msltus35.dll
-d74cc7953be48ec1f3deff4741977887  ./English/msrd2x35.dll
-17291135b3146b3c3c9d201b5d65c168  ./English/mstext35.dll
-9ba25eab9b071b8ef0799f7b785c4722  ./English/Msvcrt40.dll
-81a267f80035cb3a7559be4179700931  ./English/Ole32.dll
-b9d04a19150d6799c95045719e6e6913  ./English/Oleaut32.dll
-441e965db51513b8e3c22477832641c3  ./English/Olepro32.dll
-54e9447a8133042ba0fa293a2440527b  ./English/PcToAvigo.avi
+a943ad8f40479fa5cd68afba5787be4f  ./AVIGO/Avigo100.pgm
+48c56d5db36b20d0f8644a85d1c33dac  ./AVIGO/AvigoMgr.exe
+618341f3e7654c8d5d7e13f17bf433f8  ./AVIGO/AvigoToPc.avi
+0be37395a851b1d7aaa7039605ec12c9  ./AVIGO/Deu100.alb
+72960b3faf8c1845f37d1aac23996e6c  ./AVIGO/Download.exe
+cb4848abcb77130f48b8f9e9cf6d8977  ./AVIGO/Eng100.alb
+0e206fc4ef4a922c1de3199465ee5955  ./AVIGO/English/AvigoMan.cnt
+9095276ff7bdda4dd35b79d76397410c  ./AVIGO/English/Avigoman.hlp
+2b212e81224f2bdd608d98fe579c8c4c  ./AVIGO/Esp100.alb
+abc3474a2219fe49c2a2bf2f3e764a64  ./AVIGO/Financial100.app
+1f17ba903bc00e2694e6338c0e9bd8c3  ./AVIGO/Fra100.alb
+7265699e1bbae3022376e4f18f2e52b7  ./AVIGO/French/AVIGOMAN.HLP
+df1c526338995596901bcc95ed637f33  ./AVIGO/French/AvigoMan.cnt
+64889479798be3d1a682ebd2e1b50452  ./AVIGO/German/AvigoMan.cnt
+ec267fd5abb90d373e3b9fe6a5762315  ./AVIGO/German/Avigoman.hlp
+e21adacb76cfff3350a3e82c4f883a44  ./AVIGO/Ita100.alb
+048fa624c7f7f9ddf76898f1dd5a5418  ./AVIGO/Italian/AVIGOMAN.HLP
+85cf12ce9899c7242233a340dcb10de4  ./AVIGO/Italian/AvigoMan.cnt
+54e9447a8133042ba0fa293a2440527b  ./AVIGO/PcToAvigo.avi
+351f02281421554f722cd7ff749b8576  ./AVIGO/Readme.txt
+cd8818345ab13e0bf7627035c8a746ad  ./AVIGO/Spanish/AVIGOMAN.HLP
+676dd602591dceb83799e58c032071f1  ./AVIGO/Spanish/AvigoMan.cnt
+77abaeafbb2340ec06bd83da4b3c0418  ./AVIGO/SyncMovie.avi
+4aec6b69fd4237a2a0562974e55537ef  ./AVIGO/language.lng
+9cb48c7068f6d9389493b0f1035ab204  ./AVIGO/translat.lng
+5f854403d1e201a397151610fb9c80dd  ./AVIGO_DLL's/DLGDLL.dll
+54584845c6f232a18e4c8f7c59aeca09  ./AVIGO_DLL's/cw3220.dll
+15f24a05040bb34765c852942480dc0d  ./AVIGO_DLL's/io_common.dll
+5beb2e7cb566e103480f3f4c3b99f006  ./AVIGO_DLL's/io_error.dll
+b83f81c70983c28252c452fcdce906de  ./AVIGO_DLL's/io_ircomm.dll
+955db4b34095dc7340c82a8e328c4aa3  ./AVIGO_DLL's/io_obex.dll
+989c75747c7b24caacf2e4df0330f45c  ./AVIGO_DLL's/io_tiobex.dll
+149f277034310ea0e204a5ded4502c26  ./AVIGO_DLL's/tops.dll
+41b7178b258b97248a2e31d6771cf6f3  ./AVIGO_DLL's/update.dll
+0aba3f8d3a59754306d75c157e1d2b0a  ./DAO_Reg/dao350.dll
+87a2adf125be51cdd5d8d3843e0f0b7e  ./DAO_UnReg/Dao2535.tlb
 5caa91bc875bfdfd4066b1abdfcd6831  ./English/Readme.txt
-676dd602591dceb83799e58c032071f1  ./English/Spanish/AvigoMan.cnt
-cd8818345ab13e0bf7627035c8a746ad  ./English/Spanish/AVIGOMAN.HLP
-77abaeafbb2340ec06bd83da4b3c0418  ./English/SyncMovie.avi
-149f277034310ea0e204a5ded4502c26  ./English/tops.dll
-9cb48c7068f6d9389493b0f1035ab204  ./English/translat.lng
-41b7178b258b97248a2e31d6771cf6f3  ./English/update.dll
-9f8c2ac5719be020bd5fe898fa01f90f  ./English/vbajet32.dll
-9d1864ae5f6ff8bbde86a3f5a448110d  ./English/vbar332.dll
+441e965db51513b8e3c22477832641c3  ./OLE_Reg/Olepro32.dll
+81a267f80035cb3a7559be4179700931  ./OLE_Unreg/Ole32.dll
+b9d04a19150d6799c95045719e6e6913  ./OLE_Unreg/Oleaut32.dll
+8a7871c9b80a678813ca668338432456  ./System_Reg/msexcl35.dll
+e8a31571e9b0f79bc30ad7b8afa75c08  ./System_Reg/msjet35.dll
+6252deb3dab5e502fcab24183c642563  ./System_Reg/msltus35.dll
+d74cc7953be48ec1f3deff4741977887  ./System_Reg/msrd2x35.dll
+17291135b3146b3c3c9d201b5d65c168  ./System_Reg/mstext35.dll
+c3f50ecf458c55ac1157b98f74e6ad0f  ./System_UnReg/Comctl32.dll
+9ba25eab9b071b8ef0799f7b785c4722  ./System_UnReg/Msvcrt40.dll
+8472c0e32802199891d76d57879bd9d9  ./System_UnReg/msjint35.dll
+5773425a2bb778684b57d042a0cd5247  ./System_UnReg/msjter35.dll
+9f8c2ac5719be020bd5fe898fa01f90f  ./System_UnReg/vbajet32.dll
+9d1864ae5f6ff8bbde86a3f5a448110d  ./System_UnReg/vbar332.dll
diff --git a/test/v0/avigomanager.sh b/test/v0/avigomanager.sh
index de2cff4..8fc1c79 100755
--- a/test/v0/avigomanager.sh
+++ b/test/v0/avigomanager.sh
@@ -10,7 +10,7 @@ if [ \! -x ${UNSHIELD} ]; then
 fi
 
 DIR=`mktemp -d`
-#trap 'rm -rf ${DIR}' TERM INT EXIT
+trap 'rm -rf ${DIR}' TERM INT EXIT
 cd ${DIR}
 
 #URL=https://www.ti.com/organizers/avigo/docs/avigomanager11b22.zip
@@ -36,10 +36,10 @@ if [ ${CODE} -ne 0 ]; then
 fi
 
 cd extract2
-find . -type f | sort | xargs md5sum > ../md5
-if ! diff ${MD5_FILE} ../md5 >&2 ; then
+find . -type f -print0 | LC_ALL=C sort -z | xargs -0 md5sum > ../md5
+if ! diff -wu ${MD5_FILE} ../md5 >&2 ; then
     echo "MD5 sums diff" >&2
     exit 4
 fi
 
-exit 0
\ No newline at end of file
+exit 0
diff --git a/test/v0/baldurs_gate_patch_v1_1_4315_international.md5 b/test/v0/baldurs_gate_patch_v1_1_4315_international.md5
new file mode 100644
index 0000000..3ebec47
--- /dev/null
+++ b/test/v0/baldurs_gate_patch_v1_1_4315_international.md5
@@ -0,0 +1,132 @@
+f44ad46b463b80395ab1d385c81134b7  ./English/dialog.tlk
+078f0e7f20f588f64541c75fa5213b16  ./French/dialog.tlk
+73b29706c2e3975807347ae56b1baef3  ./French/dialogF.tlk
+e47065f6607ce2b60b4b47b50e44418e  ./German/dialog.tlk
+d1907ebe55191062a47638c55604fb24  ./German/dialogF.tlk
+296d5436b35871c776a0eea17b0d55ab  ./Italian/dialog.tlk
+d0150855642cd5df9c6c6e9e97fd91d5  ./Italian/dialogF.tlk
+9cbfa197ac49bea7b44cff3105a31cec  ./Language_Independant/BGMain.exe
+bf31b604845049664a1e71b9832c4ff9  ./Language_Independant/Override/ACTFLAM.bcs
+d41d8cd98f00b204e9800998ecf8427e  ./Language_Independant/Override/AR2100.bcs
+5736f7f134173fbc7f928e17825eaf17  ./Language_Independant/Override/AR3300.bcs
+0df6f2e721bc839a89fcd02edde1a5f4  ./Language_Independant/Override/Ar0109.ARE
+2ad128852e9785ddbadd8f3fe90a7b58  ./Language_Independant/Override/Ar0111.ARE
+f5a5fccc6df7d21259981ff113058797  ./Language_Independant/Override/Ar0145.ARE
+c864b455d4566212a5315338a7f28048  ./Language_Independant/Override/Ar0146.ARE
+c23530ef38b54ad4261c4024540f3337  ./Language_Independant/Override/Ar2300.ARE
+9a7bfc5fcbe99792b464189e32607834  ./Language_Independant/Override/Ar2600.ARE
+bb2ca8bd9fce65af090f7d076bb5cdd8  ./Language_Independant/Override/Ar2608.ARE
+5e7fd56e606543b56a6cf8b388440aea  ./Language_Independant/Override/Ar2609.ARE
+a3352f73e9c7323cb97833e1f8fedce2  ./Language_Independant/Override/Ar2610.ARE
+9b7010ef7eed7bfd323bc7e242a089ae  ./Language_Independant/Override/Ar2611.ARE
+2f73eb6c030e2fc818a392af1e95948e  ./Language_Independant/Override/Ar2612.ARE
+d44097f753e3c3bc7632c0ca25f974bf  ./Language_Independant/Override/Ar2614.ARE
+0bb9921e9cda60f750a1f8e93a48e19e  ./Language_Independant/Override/Bendal.dlg
+efd712d144b8dd63630b652d58905721  ./Language_Independant/Override/Cadder.dlg
+00b778d8d99b5a4f19f94541a47b9a0d  ./Language_Independant/Override/Caedmo.dlg
+a4cb1c738ece8b00c3b0f91942f88ea5  ./Language_Independant/Override/Drizzt.bcs
+2572ffb826e37f22c3848d0dfbeba7a8  ./Language_Independant/Override/LEAT08.itm
+ca179d10729d01df68d3c731f696a155  ./Language_Independant/Override/RING09.itm
+a4adf7fbfda3b1d21a6ff5612338999d  ./Language_Independant/Override/Skelwa.CRE
+ca05124ba6cd3c4faa8682a89053aaca  ./Language_Independant/Override/Skelwa02.CRE
+2b06acba186f30847a7abb1c1aa3b9aa  ./Language_Independant/Override/SpPr403.spl
+760bcf9a9706b5e284a3b2041830b905  ./Language_Independant/Override/SpWi107.spl
+401500c3c3faf3a631abf0166cb6b58e  ./Language_Independant/Override/SpWi116.spl
+6f337ee0e7ebe04055fc659be06bab32  ./Language_Independant/Override/Voleta.dlg
+0491a372f751668cbd63b1c0a8cd4e89  ./Language_Independant/Override/albert.CRE
+fe64a508802a4669a2eefc8636943ce3  ./Language_Independant/Override/albert.dlg
+f6065227952e197037f4a664ef656a04  ./Language_Independant/Override/amnise.dlg
+30960cf425e47e89e8f1f4dc2917c7d5  ./Language_Independant/Override/ar0700n.WED
+0195dffeb01b85f6bd45e3a821edfdb2  ./Language_Independant/Override/ar1900.bcs
+8f9a936979600c240f1e29632aee0874  ./Language_Independant/Override/ar3352.bcs
+afdc5ac03dce7340c3455647f1db32e9  ./Language_Independant/Override/ar5406.MOS
+b3ef2dd5547fe36dd6a369d3c42ec65d  ./Language_Independant/Override/belt.CRE
+5bf45a95bfc33851b5d38748b7529b1f  ./Language_Independant/Override/benjy.CRE
+a0127b3b87addf9d53a2cd899caf743a  ./Language_Independant/Override/bjorni.CRE
+0fdd621c4bf752b63d88b5ec632ce163  ./Language_Independant/Override/bolt02.itm
+65a0412b1bae0c0afa0af4c1fe0558b6  ./Language_Independant/Override/bolt03.itm
+492f176e9b115a8bd62739492786219b  ./Language_Independant/Override/bolt04.itm
+8eeb446b0f02c118d477a9e77768cdd4  ./Language_Independant/Override/bolt05.itm
+6ef2de15ee29e51ed88f9e8a0679ae93  ./Language_Independant/Override/bolt06.itm
+408e1f21c97a4ddeee02c6f98ccf35d6  ./Language_Independant/Override/boot02.itm
+3b67d3bb38e7cb0859b831de73e2a920  ./Language_Independant/Override/bow01.itm
+da427230ff40667488e8da123bc858e4  ./Language_Independant/Override/bow02.itm
+56ccef981ba1c3778a17eee9cb60d49f  ./Language_Independant/Override/brage2.CRE
+13ef5bd132873f9296eb4d4635e62338  ./Language_Independant/Override/branwe.CRE
+655e75b123d88c168e7d19c278a1eb46  ./Language_Independant/Override/calaha.dlg
+fa50aca69104b6578a8df6cadc220446  ./Language_Independant/Override/chan06.itm
+22167d0e6d74356d411f42124370f27f  ./Language_Independant/Override/childulg.dlg
+a1d3a31b9e598ea45a5d45fc4cbb53dc  ./Language_Independant/Override/davaeo.CRE
+deee772fc7fb3e5a849bbb664bca9f41  ./Language_Independant/Override/dink.dlg
+0db446157a7d034c1c896a50eb327af7  ./Language_Independant/Override/divine.dlg
+b64e887c706335f42a300f7935348dd8  ./Language_Independant/Override/dradee.dlg
+a60c708166b6adb5c6c4c11c0d4fd78b  ./Language_Independant/Override/drizzt.CRE
+d696f9accc2f86f54df842516013808b  ./Language_Independant/Override/evalt.dlg
+3d84d85860613c6092412ae6b4953669  ./Language_Independant/Override/farthi.dlg
+4475aae986b6cc0bd4a0e384efe2ac07  ./Language_Independant/Override/fenrus.dlg
+27dc860406637f616c9396bf334528ae  ./Language_Independant/Override/fenten.dlg
+a4dc2c28612f3b6892a3f23b20502c90  ./Language_Independant/Override/firebe.CRE
+680781e9ccf32fab8994618c7f865afd  ./Language_Independant/Override/flam13.CRE
+f1e9f431db953e7cc45697adcf4680f0  ./Language_Independant/Override/flam2.dlg
+bd81430094ae1c047a6ef69ebc558076  ./Language_Independant/Override/ftowbez.dlg
+bd5c387a4613afb6ee1bcb3d70b51554  ./Language_Independant/Override/ftown2.dlg
+0cf1b83d35e21e54f9c1000d22e7b3b3  ./Language_Independant/Override/gandol.dlg
+9796cc9316a92b77a35c532e3ec8b74e  ./Language_Independant/Override/gatewa2.dlg
+163d1d07a68acf1d1118b0d840860722  ./Language_Independant/Override/gatewere.dlg
+1e9cb82c54b77174f133765455465021  ./Language_Independant/Override/gnarl.dlg
+a3c68400b10091a9a68cd130ef55570a  ./Language_Independant/Override/gnoll5.bcs
+7a407fd1b6b860537771417c2db21276  ./Language_Independant/Override/gnoll5.dlg
+1a1be4486488392c982dff51af9ccdc8  ./Language_Independant/Override/gnolldr.bcs
+d1204551cd327c4d9ea051bd2c56536e  ./Language_Independant/Override/husam.dlg
+6f1b7a1821c4c55533c2b905f43d4115  ./Language_Independant/Override/islsir.dlg
+3fec0eb719f037472c0f93d212a0aaf0  ./Language_Independant/Override/jaheir6.CRE
+b5db08dd4aa6423b1c714be04b51dfbc  ./Language_Independant/Override/jorin.dlg
+4231a7055dbf282d49bc3cb4483ec797  ./Language_Independant/Override/kryla.dlg
+58d654666cc52b8fc240655e09fec3ea  ./Language_Independant/Override/lahl.dlg
+7240ae40425fdba71a3d5b4ea6ca1495  ./Language_Independant/Override/liia.CRE
+4e9e1acf62d7a42e0829a3500560e816  ./Language_Independant/Override/lothan.dlg
+0cc09ec3fed6a0573290203f113eb716  ./Language_Independant/Override/maltz.dlg
+8cae66fe89641b4862f509ddf3c0c8fd  ./Language_Independant/Override/marale.dlg
+6e120e8f604a6fb138b444c6daef7df9  ./Language_Independant/Override/memnis.dlg
+a13cb3e24b3a1ce88bf6aaf8c30c18a1  ./Language_Independant/Override/misc72.itm
+2992b58f9bca3919e5545d2b9db33e00  ./Language_Independant/Override/misc89.itm
+2a073fca4785ffe64261608b376584ef  ./Language_Independant/Override/mtowbez.dlg
+485b5d06cbdcd0d9d58d5397d183e2bf  ./Language_Independant/Override/mulahe.CRE
+d2b720feadcf2ffa27bc5726903c2e95  ./Language_Independant/Override/nadin.dlg
+dcfe8b78790df6d65ef14a240145b231  ./Language_Independant/Override/nalin.CRE
+dc854e9da3bb3739fe501017c764c509  ./Language_Independant/Override/narlen.dlg
+9189a9a8216a58628e7e1713f88adb7d  ./Language_Independant/Override/nikola.CRE
+35c08e8869e4c62ef55f22c880961f82  ./Language_Independant/Override/ogrelead.dlg
+21d7243f053a64ceb267394822fe7ac5  ./Language_Independant/Override/oublek.dlg
+405531ccf46cac6574e093324e5f996b  ./Language_Independant/Override/palin.dlg
+3721269a403a5ad7970fb113aa4c36a7  ./Language_Independant/Override/potn40.itm
+56c493ca7aab27dc1aa94a1649047777  ./Language_Independant/Override/ragefa.CRE
+25dc632981540c49aa6d8cf129b1bcc6  ./Language_Independant/Override/ragefa.dlg
+4f8adfd0e59f3047615c1392ac64861b  ./Language_Independant/Override/ramazi.CRE
+dc17a97ddfa215d0c7da0afac28e642a  ./Language_Independant/Override/ramazi.dlg
+3e9f4d5f5261c864e77e2a8175c4f48e  ./Language_Independant/Override/sarevo.dlg
+7be6d7f2bf5734b4c0dbe93f2ceef6f6  ./Language_Independant/Override/sarevok.bcs
+1465c6d411a8f32546a26a189c09dc95  ./Language_Independant/Override/schlum.CRE
+d772e8dea7973c3a95d341c45552421c  ./Language_Independant/Override/schlum1.itm
+eaeb861e9470bacddd5f9cb39f1c8149  ./Language_Independant/Override/shoal.dlg
+459bd037be0ae24ebb6cc10a002a0dcd  ./Language_Independant/Override/silenc.dlg
+44859c480791275bb8acd6929a862edf  ./Language_Independant/Override/skelwa03.CRE
+432040033cdd060d28bd5810edb87dac  ./Language_Independant/Override/spwi313.spl
+a8f88138ed6beb1df1e34085c5a9c4a1  ./Language_Independant/Override/sw2h06.itm
+fae46d1893f8bdab8fe2b8c37d4e7e38  ./Language_Independant/Override/taloun.dlg
+97659d8a158ff9d465600470981dd8bc  ./Language_Independant/Override/tem2304.STO
+529b1a213a4f37915fab7e389d675224  ./Language_Independant/Override/tem4802.STO
+ee55ee4e14ff258ac04e2567f1372f46  ./Language_Independant/Override/tethto2.dlg
+16f10e640d0420c4a6a0b064c11b4a1c  ./Language_Independant/Override/thalan.dlg
+5b6b091576f7fde26c96505c9be3a927  ./Language_Independant/Override/therel.dlg
+885b5e2a5cf200ab2d15974872a0518d  ./Language_Independant/Override/tick.dlg
+1defb39a2f307a6ed027c04f052b8e83  ./Language_Independant/Override/tremai.dlg
+9cab96c801bc2ee5598f28a04db41a86  ./Language_Independant/Override/ulcast.dlg
+9449663f07b5cdf1bc5b8704dd258beb  ./Language_Independant/Override/ulraun.dlg
+a08081bec7dbe2465a7524a756dfd0c4  ./Language_Independant/Override/unshey.dlg
+18ca62661ff16cb69c2a06781ce5a408  ./Language_Independant/Override/viconi.dlg
+24db078462d81aeebe007e8f7aaf1506  ./Language_Independant/Override/voltin.CRE
+cfd5b84d34910a486e648d82d0d7b37c  ./Language_Independant/Override/xan6.CRE
+14d20a1c15087b551e4d08ae56a643c2  ./Language_Independant/Override/yeslick.bcs
+afd8570cf7b78630c002464b31790645  ./Spanish/dialog.tlk
+7f7826a38750b3aba1da421f1100cbc6  ./Spanish/dialogF.tlk
diff --git a/test/v0/baldurs_gate_patch_v1_1_4315_international.sh b/test/v0/baldurs_gate_patch_v1_1_4315_international.sh
new file mode 100755
index 0000000..eb89638
--- /dev/null
+++ b/test/v0/baldurs_gate_patch_v1_1_4315_international.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+set -e
+cd `dirname $0`
+MD5_FILE=`pwd`/`basename $0 .sh`.md5
+UNSHIELD=${UNSHIELD:-/var/tmp/unshield/bin/unshield}
+
+if [ \! -x ${UNSHIELD} ]; then
+    echo "unshield executable not found at $UNSHIELD" >&2
+    exit 1
+fi
+
+DIR=`mktemp -d`
+trap 'rm -rf ${DIR}' TERM INT EXIT
+cd ${DIR}
+
+URL="https://www.dropbox.com/s/9ruil8oi6amjbbk/unshield-baldurs_gate_patch_v1_1_4315_international.zip?dl=1"
+curl -fsSL -o test.zip ${URL}
+unzip -q test.zip 'data*'
+
+set +e
+timeout 10 ${UNSHIELD} -d extract1 x data1.cab > log2 2>&1
+CODE=$?
+if [ ${CODE} -ne 0 ]; then
+    cat log2 >&2
+    echo "unshield failed with error $CODE" >&2
+    echo "See https://github.com/twogood/unshield/issues/70" >&2
+    exit 2
+fi
+
+cd extract1
+find . -type f | LC_ALL=C sort | xargs md5sum > ../md5
+if ! diff -wu ${MD5_FILE} ../md5 >&2 ; then
+    echo "MD5 sums diff" >&2
+    echo "See https://github.com/twogood/unshield/issues/70" >&2
+    exit 3
+fi
+
+exit 0
diff --git a/test/v0/the-feeble-files-spanish.md5 b/test/v0/the-feeble-files-spanish.md5
index 7cd0688..a0dbaa4 100644
--- a/test/v0/the-feeble-files-spanish.md5
+++ b/test/v0/the-feeble-files-spanish.md5
@@ -6,9 +6,9 @@ de4f46b96872f50ed9a9bc86e3f3b74f  ./Essential_Game_Files/0071.VGA
 c9984357a5534e05b9d3f7da36856730  ./Essential_Game_Files/0072.VGA
 a884cd4b8597f40e9557ef4a7ca80031  ./Essential_Game_Files/0081.VGA
 e465c315cbe92ba02821c8e9ff927777  ./Essential_Game_Files/0082.VGA
+a1af4636fe0d3286d17d0aa6ca89fda4  ./Essential_Game_Files/0091.VGA
 a1af4636fe0d3286d17d0aa6ca89fda4  ./Essential_Game_Files/0091.fst
 1f8c398703d331547b1b0c33de176eed  ./Essential_Game_Files/0091.slw
-a1af4636fe0d3286d17d0aa6ca89fda4  ./Essential_Game_Files/0091.VGA
 34f3dd6e1b6978a0b05ef8b0c33557f4  ./Essential_Game_Files/0092.VGA
 b089d0826fcd31f4cee07821c421f8b8  ./Essential_Game_Files/0111.VGA
 81a2356eaa10b64e96c1df514c613ad7  ./Essential_Game_Files/0112.VGA
@@ -281,16 +281,12 @@ aeb37c757f102ff4ca3d76db07eec04c  ./Essential_Game_Files/3332.VGA
 ecb26c965ca8b45e3a1856fc17a21b9e  ./Essential_Game_Files/Disk2.smk
 b8f09cb0f9d811c32e5bdb07aac08584  ./Essential_Game_Files/Disk3.smk
 f2ce346f8f45c0d362f432ad5fe1b6dd  ./Essential_Game_Files/Disk4.smk
-ae84d7898b6282127618069d9c586246  ./Essential_Game_Files/feeinbin.ico
 24fe7ba975369c272088aa3b0c5bf348  ./Essential_Game_Files/GAME22
-c1fa9f0e1726e9a95638b53b1d087468  ./Essential_Game_Files/icklfeeb.ico
 e445a0a7e554ebcb550a52ee6e74023e  ./Essential_Game_Files/Nextdoor.smk
 c86a414aa0101d0838b6c5e20dd5e99c  ./Essential_Game_Files/Omnitoy.smk
 754e03f61a1186dd47b31ee7798fc704  ./Essential_Game_Files/Qtime.smk
 c4a0b8193335026c5b220257dea2c585  ./Essential_Game_Files/Run95.exe
-71512fc98501a8071a26b683a31dde78  ./Essential_Game_Files/save.999
 7635d1e15ba1704b3cb1525c1eba0d6f  ./Essential_Game_Files/SMACKW32.DLL
-e00cead9fb77c8a6b48b9a8fe98af527  ./Essential_Game_Files/startup.wav
 4157c16894c0413ca64e56a52aa46d50  ./Essential_Game_Files/TABLES01
 d71b7918c74a999fa4c539ee8ef63003  ./Essential_Game_Files/TABLES02
 ae33ef52caed416c1f29c2976736ac4f  ./Essential_Game_Files/TABLES03
@@ -317,3 +313,7 @@ c521eb8fe621ddb1a1e112fc679ef1b4  ./Essential_Game_Files/TABLES21
 b50f2a67685e05b792afd5edf894ebeb  ./Essential_Game_Files/TABLES24
 a7add5ae7548d332982c234a81bfb03f  ./Essential_Game_Files/TABLES25
 0bbfee8e69739111eb36b0d138da8ddf  ./Essential_Game_Files/TBLLIST
+ae84d7898b6282127618069d9c586246  ./Essential_Game_Files/feeinbin.ico
+c1fa9f0e1726e9a95638b53b1d087468  ./Essential_Game_Files/icklfeeb.ico
+71512fc98501a8071a26b683a31dde78  ./Essential_Game_Files/save.999
+e00cead9fb77c8a6b48b9a8fe98af527  ./Essential_Game_Files/startup.wav
diff --git a/test/v0/the-feeble-files-spanish.sh b/test/v0/the-feeble-files-spanish.sh
index 61ceeb9..92a4fc0 100755
--- a/test/v0/the-feeble-files-spanish.sh
+++ b/test/v0/the-feeble-files-spanish.sh
@@ -28,8 +28,8 @@ if [ ${CODE} -ne 0 ]; then
 fi
 
 cd extract1
-find . -type f | sort | xargs md5sum > ../md5
-if ! diff ${MD5_FILE} ../md5 >&2 ; then
+find . -type f | LC_ALL=C sort | xargs md5sum > ../md5
+if ! diff -wu ${MD5_FILE} ../md5 >&2 ; then
     echo "MD5 sums diff" >&2
     echo "See https://github.com/twogood/unshield/issues/27" >&2
     exit 3
diff --git a/test/v0/wireplay.md5 b/test/v0/wireplay.md5
new file mode 100644
index 0000000..07a3e22
--- /dev/null
+++ b/test/v0/wireplay.md5
@@ -0,0 +1,108 @@
+596e93bd517f9d9056db083e1a445c63  ./Program_Executable_Files/CLIENT.EXE
+b7ef49b0dc87484a7dfd97cb67e47195  ./Program_Executable_Files/GAME.DAT
+3c2937f573b9f5889727cd5818a7b37c  ./Program_Executable_Files/HELP/ABOUT.HTM
+9880b2b6081c754a264ec4ff75e84ac7  ./Program_Executable_Files/HELP/BIGRED.HTM
+7f0329ee1840ef8ed654292a145bebc1  ./Program_Executable_Files/HELP/BRINST.HTM
+b14f65893801344852def3f75ceff4f0  ./Program_Executable_Files/HELP/BRRDEMO.HTM
+f74df3dcc0556b5a744db903530635d2  ./Program_Executable_Files/HELP/CLUBSOC.HTM
+8a22ac5602edd904309aae4df407a158  ./Program_Executable_Files/HELP/COMANCHE.HTM
+76f8f8921e5ed58121836b3d61be4ac2  ./Program_Executable_Files/HELP/COMMAND.HTM
+463145d71702e2733c14f1f916c5332d  ./Program_Executable_Files/HELP/DESC2DEM.HTM
+191dd050b10c7d1e10ea6683d356def5  ./Program_Executable_Files/HELP/DESCENT.HTM
+923b1e2791d03e83e1eebdeafb5e9451  ./Program_Executable_Files/HELP/DESCENT2.HTM
+7b428da96eb62dedcfa4831be4b886e2  ./Program_Executable_Files/HELP/DOOM1666.HTM
+a8999012e87a8a00529905359452f89b  ./Program_Executable_Files/HELP/DOOM19.HTM
+14ce54b1f77b38f2b92c8fba0499aa81  ./Program_Executable_Files/HELP/DOOM2.HTM
+22a42663824d6fb724960bb8b8594089  ./Program_Executable_Files/HELP/DOSHELP.HTM
+4defdbf79a09988bb83f3c1ddefb3a41  ./Program_Executable_Files/HELP/DOSNEW.HTM
+a2ce6b14611732067d09edffc0796daa  ./Program_Executable_Files/HELP/DUKE3D.HTM
+6a907eb648b5cef907974fa88cfa0609  ./Program_Executable_Files/HELP/DUMMY.HTM
+014487445e79cef96d24b5833074c52e  ./Program_Executable_Files/HELP/EF2000.HTM
+3f9283d47ce65f72abcab41b0516d23f  ./Program_Executable_Files/HELP/EFINST.HTM
+94c7dc53aeb52a59b8a47bc6638b1bc2  ./Program_Executable_Files/HELP/EURO96.HTM
+b086b0550b89886c5c21fb15051bf192  ./Program_Executable_Files/HELP/EXTREME.HTM
+8697f3c42cc0c4f8513cb44c70ff51e1  ./Program_Executable_Files/HELP/FIRCON.IMG
+e3550453cb1b399c0bddecc0a57ca4b1  ./Program_Executable_Files/HELP/GAME0.HTM
+ab609af26e13d4b9e7abaab8c4ea3d5c  ./Program_Executable_Files/HELP/GAMETEST.HTM
+9b238951bcf412905869d93de78fea5a  ./Program_Executable_Files/HELP/GENERAL.HTM
+8cd56e7de3cd600edc68df08149b4cfa  ./Program_Executable_Files/HELP/HAND1.IMG
+7be093ead913ff28348fc47297f93688  ./Program_Executable_Files/HELP/HAND2.IMG
+4fc377a78e97e56f6907b2b6fa4608df  ./Program_Executable_Files/HELP/HANDCURS.IMG
+e7709ec7c8e398c83eea36715024cfa5  ./Program_Executable_Files/HELP/HELP.HTM
+1db8a0787fa72fa3587b451372e0d2c7  ./Program_Executable_Files/HELP/HELP35.HTM
+bf963b7ecc1d7a920cca7cc32aa294c2  ./Program_Executable_Files/HELP/HELP36.HTM
+ae5a63ac93fb75b5be5b0d11f1c58ec2  ./Program_Executable_Files/HELP/HELP_10.HTM
+d909409d4a25e373968b1613df201005  ./Program_Executable_Files/HELP/HELP_11.HTM
+b1ca129c4c900a8920be3c2c6a482815  ./Program_Executable_Files/HELP/HELP_12.HTM
+1eff62c4be4cea2841f52cc6a32ca39d  ./Program_Executable_Files/HELP/HELP_13.HTM
+1fc55c91fdd87321c2ef8e5c223dfd62  ./Program_Executable_Files/HELP/HELP_14.HTM
+bbecf18f02490fe4b3005c72ba426f96  ./Program_Executable_Files/HELP/HELP_2.HTM
+9dd3468c18461cc67e8dd99cc84638c5  ./Program_Executable_Files/HELP/HELP_3.HTM
+063ccdc42a2b1587763484bde2ae8f77  ./Program_Executable_Files/HELP/HELP_3A.HTM
+dcdf3be39e46104e21b09418fe47a5d4  ./Program_Executable_Files/HELP/HELP_4.HTM
+39585902b1296b78b5af9f41843366ee  ./Program_Executable_Files/HELP/HELP_4A.HTM
+1cade7e5d5d88ea3e274f50282aa8f7f  ./Program_Executable_Files/HELP/HELP_5.HTM
+3a42d43855b5b5fe359fb1195422aa1a  ./Program_Executable_Files/HELP/HELP_6.HTM
+c6ef44048c86cad34ff36f57e683baf9  ./Program_Executable_Files/HELP/HELP_6A.HTM
+458be696aee2a6c918efd6123df28a10  ./Program_Executable_Files/HELP/HELP_6B.HTM
+191d75ae2e28e58fe4974df7b4156273  ./Program_Executable_Files/HELP/HELP_6C.HTM
+d44e064c9ee3941d38f30999ac133797  ./Program_Executable_Files/HELP/HELP_6D.HTM
+8ef96c25a1ac1e3d624d2ce99d5c5cb0  ./Program_Executable_Files/HELP/HELP_7.HTM
+b2f58a64fbf6f4656c3dfe4bd2013665  ./Program_Executable_Files/HELP/HELP_7A.HTM
+0e67a6f3e0e27f1fc25b5f920fea69c0  ./Program_Executable_Files/HELP/HELP_7B.HTM
+f0f2990440fceb30eb053e72781409b0  ./Program_Executable_Files/HELP/HELP_7C.HTM
+87a448f01235e4214032a4f0d14eac60  ./Program_Executable_Files/HELP/HELP_7D.HTM
+6d751202eb9dd7dca209d0afa5ab5ac6  ./Program_Executable_Files/HELP/HELP_7E.HTM
+d475add6ba4d2907a594bba09ceb48da  ./Program_Executable_Files/HELP/HELP_8.HTM
+9ece5f2ea55cd083ce8155a734d04817  ./Program_Executable_Files/HELP/HELP_9.HTM
+982db919ca7c9494056d3f02d75cd8b1  ./Program_Executable_Files/HELP/HELP_9A.HTM
+aaf5a0c62d7ef6458d5471ee87766b19  ./Program_Executable_Files/HELP/HELP_9AA.HT
+aaf5a0c62d7ef6458d5471ee87766b19  ./Program_Executable_Files/HELP/HELP_9AA.HTM
+ff5e0a17ddef735b37f82e76c8f1f9aa  ./Program_Executable_Files/HELP/HELP_9B.HTM
+c681509bdfaedcb5118a4632b3e9e974  ./Program_Executable_Files/HELP/HELP_9C.HTM
+3d188e186bfdb97631e96bf63d231fb2  ./Program_Executable_Files/HELP/HELP_9D.HTM
+3a15d091cec2a5f6a54ce93a798b30a2  ./Program_Executable_Files/HELP/HELP_9E.HTM
+1c6bc3ecb9a12c587ec690196875d0db  ./Program_Executable_Files/HELP/HELP_9F.HTM
+40a1e53d2464e73138ada299d583f12a  ./Program_Executable_Files/HELP/HELP_9G.HTM
+147d6fb6fa0b38ad02a53eb0cc25a01e  ./Program_Executable_Files/HELP/HELP_9H.HTM
+a5a17b695104caa76df3b75bed5b9444  ./Program_Executable_Files/HELP/HELP_9J.HTM
+26a2689b8fadcdca9ee5b7e87d1ef31e  ./Program_Executable_Files/HELP/HELP_9K.HTM
+ecebeeda0e0d6d072870a4d740e04f6f  ./Program_Executable_Files/HELP/IGICON.IMG
+d02f2d21cea8528f55059561040c633f  ./Program_Executable_Files/HELP/INLOCK.IMG
+d3a40fcc32b7e71080f2af2949dcddc8  ./Program_Executable_Files/HELP/NASCAR2.HTM
+a48ac1d03486e8bab54a728fcbe335b2  ./Program_Executable_Files/HELP/NETMECH.HTM
+257d7dcd16f715da5dfada89fd4963fa  ./Program_Executable_Files/HELP/OFFLINE.IMG
+1de08313c99ca991ef7b5ecdd4dddf9b  ./Program_Executable_Files/HELP/OUTLOCK.IMG
+cd86dfa2c129577020ebf537d85d5df7  ./Program_Executable_Files/HELP/PAGEABLE.IMG
+17c627f77fdabb20f9b62d9ce4478cd7  ./Program_Executable_Files/HELP/POINTER1.IMG
+5226c2dfd554935259070ba27f3a5979  ./Program_Executable_Files/HELP/POINTER2.IMG
+61346266968fbcb1e4a436bd344b41ed  ./Program_Executable_Files/HELP/REDALERT.HTM
+33c753c67c8b69d21444a200cc86dec6  ./Program_Executable_Files/HELP/REDNECK.HTM
+e1216b38e9f8b76c17ae170dc67666f5  ./Program_Executable_Files/HELP/SHADOWSW.HTM
+257db161d6726e3ed364c8cb9ae8ff83  ./Program_Executable_Files/HELP/TERMINAL.HTM
+f6d039a634c2f8e1d88a73d8b88f0308  ./Program_Executable_Files/HELP/ULTIDOOM.HTM
+199ffc6c3a250279fb5528367a81149e  ./Program_Executable_Files/HELP/VPOOL.HTM
+30f5028f06b5c9d0bdff8c7e9c78c0ab  ./Program_Executable_Files/HELP/VSNOOKER.HTM
+71e05df263430a89116ce7d897e11b25  ./Program_Executable_Files/HELP/WAR2DEMO.HTM
+227ccc1c11592c0f35ac9cb15074311c  ./Program_Executable_Files/HELP/WARCRAF2.HTM
+b80196f5414e9253b4ab7550657c781f  ./Program_Executable_Files/HELP/WIREAPI.HTM
+b89989c6d74e52ee1beb3bf18f194726  ./Program_Executable_Files/HELP/WIRECOMM.HTM
+491e367a7900888b96defa7ff592bfc9  ./Program_Executable_Files/HELP/WIREDOOM.HTM
+5bd772d47f1d13794e7810422e62dad3  ./Program_Executable_Files/HELP/WIREDP.HTM
+50ccb10071ba7b4a95c472b1666415bb  ./Program_Executable_Files/HELP/WIREIP.HTM
+69b3c48830a176f781b7af805160f7eb  ./Program_Executable_Files/HELP/WIREIPX.HTM
+cf2dceb995d1c075f79d26435142083e  ./Program_Executable_Files/HELP/WPDRVRS.HTM
+5184100495b9f83c3fb32767d160524b  ./Program_Executable_Files/LAUNCHER.INI
+fe62f30206b08e17d00a6e68c1f42692  ./Program_Executable_Files/MODEM.DAT
+c7d807185a6f4bbe10c143dec7156c4b  ./Program_Executable_Files/PSTUB.EXE
+74f7bfff760eb090d9e497142b84ccb2  ./Program_Executable_Files/Readme.txt
+479e2b6aaea1723043a97f4a7b5a17ec  ./Program_Executable_Files/USERS.INI
+886faf562d08664ce941cce3bfb7769e  ./Program_Executable_Files/V20.RES
+cb43a12a08b8bd9754483482115ed619  ./Program_Executable_Files/WIRECOMM.EXE
+5141cef0ebfa2d204baa01986615c906  ./Program_Executable_Files/WIREDOOM.EXE
+664bcc356a9d0068538df71baa45205e  ./Program_Executable_Files/WIREIPX.EXE
+2aaa0afb9213c9fccaea0bf7b44d6254  ./Program_Executable_Files/WIREPLAY.BAT
+0fff40618a359f26515427b30c9aae8a  ./Program_Executable_Files/WIREPLAY.CFG
+eecde17e712b9bf274f70254f49dbcb4  ./Program_Executable_Files/WIREPLAY.INI
+34f1efa56118a6220822205f0b5f2080  ./Program_Executable_Files/WIREPLAY.PAL
+db5ea5dd885a508e7273b10c8f60bb86  ./Program_Executable_Files/WPGAME.EXE
diff --git a/test/v0/wireplay.sh b/test/v0/wireplay.sh
new file mode 100755
index 0000000..5554814
--- /dev/null
+++ b/test/v0/wireplay.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+set -e
+cd "$(dirname "$0")"
+MD5_FILE=$(pwd)/$(basename "$0" .sh).md5
+UNSHIELD=${UNSHIELD:-/var/tmp/unshield/bin/unshield}
+
+if [ \! -x "${UNSHIELD}" ]; then
+    echo "unshield executable not found at $UNSHIELD" >&2
+    exit 1
+fi
+
+DIR=$(mktemp -d)
+trap 'rm -rf ${DIR}' TERM INT EXIT
+cd "${DIR}"
+
+URL="https://www.dropbox.com/s/ac3418ds94j5542/dpcb1197-Wireplay.zip?dl=1"
+curl -sSL -o test.zip "${URL}"
+unzip -q test.zip
+
+set +e
+
+timeout 10 "${UNSHIELD}" -O -d extract x dpcb1197-Wireplay/DOS/data1.cab > log 2>&1
+CODE=$?
+if [ ${CODE} -ne 0 ]; then
+    cat log >&2
+    echo "unshield failed with error $CODE" >&2
+    exit 3
+fi
+
+cd extract
+find . -type f -print0 | LC_ALL=C sort -z | xargs -0 md5sum > ../md5
+if ! diff -wu "${MD5_FILE}" ../md5 >&2 ; then
+    echo "MD5 sums diff" >&2
+    exit 4
+fi
+
+exit 0
diff --git a/test/v5/CVE-2015-1386/CVE-2015-1386.sh b/test/v5/CVE-2015-1386/CVE-2015-1386.sh
index 8fb3b4e..c71d999 100755
--- a/test/v5/CVE-2015-1386/CVE-2015-1386.sh
+++ b/test/v5/CVE-2015-1386/CVE-2015-1386.sh
@@ -1,4 +1,10 @@
 #!/bin/bash
+
+if [ "$(uname)" != "Linux" ] ; then
+    echo "This test can only run on Linux  "
+    exit 0
+fi
+
 set -e
 cd `dirname $0`
 MD5_FILE=`pwd`/`basename $0 .sh`.md5
diff --git a/win32_msvc/dirent.h b/win32_msvc/dirent.h
new file mode 100644
index 0000000..ad9d2b3
--- /dev/null
+++ b/win32_msvc/dirent.h
@@ -0,0 +1,929 @@
+/*
+ * Dirent interface for Microsoft Visual Studio
+ * Version 1.21
+ *
+ * Copyright (C) 2006-2012 Toni Ronkko
+ * This file is part of dirent.  Dirent may be freely distributed
+ * under the MIT license.  For all details and documentation, see
+ * https://github.com/tronkko/dirent
+ */
+#ifndef DIRENT_H
+#define DIRENT_H
+
+/*
+ * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
+ * Windows Sockets 2.0.
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+#   define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+/* Indicates that d_type field is available in dirent structure */
+#define _DIRENT_HAVE_D_TYPE
+
+/* Indicates that d_namlen field is available in dirent structure */
+#define _DIRENT_HAVE_D_NAMLEN
+
+/* Entries missing from MSVC 6.0 */
+#if !defined(FILE_ATTRIBUTE_DEVICE)
+#   define FILE_ATTRIBUTE_DEVICE 0x40
+#endif
+
+/* File type and permission flags for stat(), general mask */
+#if !defined(S_IFMT)
+#   define S_IFMT _S_IFMT
+#endif
+
+/* Directory bit */
+#if !defined(S_IFDIR)
+#   define S_IFDIR _S_IFDIR
+#endif
+
+/* Character device bit */
+#if !defined(S_IFCHR)
+#   define S_IFCHR _S_IFCHR
+#endif
+
+/* Pipe bit */
+#if !defined(S_IFFIFO)
+#   define S_IFFIFO _S_IFFIFO
+#endif
+
+/* Regular file bit */
+#if !defined(S_IFREG)
+#   define S_IFREG _S_IFREG
+#endif
+
+/* Read permission */
+#if !defined(S_IREAD)
+#   define S_IREAD _S_IREAD
+#endif
+
+/* Write permission */
+#if !defined(S_IWRITE)
+#   define S_IWRITE _S_IWRITE
+#endif
+
+/* Execute permission */
+#if !defined(S_IEXEC)
+#   define S_IEXEC _S_IEXEC
+#endif
+
+/* Pipe */
+#if !defined(S_IFIFO)
+#   define S_IFIFO _S_IFIFO
+#endif
+
+/* Block device */
+#if !defined(S_IFBLK)
+#   define S_IFBLK 0
+#endif
+
+/* Link */
+#if !defined(S_IFLNK)
+#   define S_IFLNK 0
+#endif
+
+/* Socket */
+#if !defined(S_IFSOCK)
+#   define S_IFSOCK 0
+#endif
+
+/* Read user permission */
+#if !defined(S_IRUSR)
+#   define S_IRUSR S_IREAD
+#endif
+
+/* Write user permission */
+#if !defined(S_IWUSR)
+#   define S_IWUSR S_IWRITE
+#endif
+
+/* Execute user permission */
+#if !defined(S_IXUSR)
+#   define S_IXUSR 0
+#endif
+
+/* Read group permission */
+#if !defined(S_IRGRP)
+#   define S_IRGRP 0
+#endif
+
+/* Write group permission */
+#if !defined(S_IWGRP)
+#   define S_IWGRP 0
+#endif
+
+/* Execute group permission */
+#if !defined(S_IXGRP)
+#   define S_IXGRP 0
+#endif
+
+/* Read others permission */
+#if !defined(S_IROTH)
+#   define S_IROTH 0
+#endif
+
+/* Write others permission */
+#if !defined(S_IWOTH)
+#   define S_IWOTH 0
+#endif
+
+/* Execute others permission */
+#if !defined(S_IXOTH)
+#   define S_IXOTH 0
+#endif
+
+/* Maximum length of file name */
+#if !defined(PATH_MAX)
+#   define PATH_MAX MAX_PATH
+#endif
+#if !defined(FILENAME_MAX)
+#   define FILENAME_MAX MAX_PATH
+#endif
+#if !defined(NAME_MAX)
+#   define NAME_MAX FILENAME_MAX
+#endif
+
+/* File type flags for d_type */
+#define DT_UNKNOWN 0
+#define DT_REG S_IFREG
+#define DT_DIR S_IFDIR
+#define DT_FIFO S_IFIFO
+#define DT_SOCK S_IFSOCK
+#define DT_CHR S_IFCHR
+#define DT_BLK S_IFBLK
+#define DT_LNK S_IFLNK
+
+/* Macros for converting between st_mode and d_type */
+#define IFTODT(mode) ((mode) & S_IFMT)
+#define DTTOIF(type) (type)
+
+/*
+ * File type macros.  Note that block devices, sockets and links cannot be
+ * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
+ * only defined for compatibility.  These macros should always return false
+ * on Windows.
+ */
+#if !defined(S_ISFIFO)
+#   define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISDIR)
+#   define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG)
+#   define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISLNK)
+#   define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK)
+#   define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISCHR)
+#   define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISBLK)
+#   define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
+#endif
+
+/* Return the exact length of d_namlen without zero terminator */
+#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
+
+/* Return number of bytes needed to store d_namlen */
+#define _D_ALLOC_NAMLEN(p) (PATH_MAX)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Wide-character version */
+struct _wdirent {
+    /* Always zero */
+    long d_ino;
+
+    /* Structure size */
+    unsigned short d_reclen;
+
+    /* Length of name without \0 */
+    size_t d_namlen;
+
+    /* File type */
+    int d_type;
+
+    /* File name */
+    wchar_t d_name[PATH_MAX];
+};
+typedef struct _wdirent _wdirent;
+
+struct _WDIR {
+    /* Current directory entry */
+    struct _wdirent ent;
+
+    /* Private file data */
+    WIN32_FIND_DATAW data;
+
+    /* True if data is valid */
+    int cached;
+
+    /* Win32 search handle */
+    HANDLE handle;
+
+    /* Initial directory name */
+    wchar_t *patt;
+};
+typedef struct _WDIR _WDIR;
+
+static _WDIR *_wopendir (const wchar_t *dirname);
+static struct _wdirent *_wreaddir (_WDIR *dirp);
+static int _wclosedir (_WDIR *dirp);
+static void _wrewinddir (_WDIR* dirp);
+
+
+/* For compatibility with Symbian */
+#define wdirent _wdirent
+#define WDIR _WDIR
+#define wopendir _wopendir
+#define wreaddir _wreaddir
+#define wclosedir _wclosedir
+#define wrewinddir _wrewinddir
+
+
+/* Multi-byte character versions */
+struct dirent {
+    /* Always zero */
+    long d_ino;
+
+    /* Structure size */
+    unsigned short d_reclen;
+
+    /* Length of name without \0 */
+    size_t d_namlen;
+
+    /* File type */
+    int d_type;
+
+    /* File name */
+    char d_name[PATH_MAX];
+};
+typedef struct dirent dirent;
+
+struct DIR {
+    struct dirent ent;
+    struct _WDIR *wdirp;
+};
+typedef struct DIR DIR;
+
+static DIR *opendir (const char *dirname);
+static struct dirent *readdir (DIR *dirp);
+static int closedir (DIR *dirp);
+static void rewinddir (DIR* dirp);
+
+
+/* Internal utility functions */
+static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
+static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
+
+static int dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count);
+
+static int dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes,
+    const wchar_t *wcstr,
+    size_t count);
+
+static void dirent_set_errno (int error);
+
+/*
+ * Open directory stream DIRNAME for read and return a pointer to the
+ * internal working area that is used to retrieve individual directory
+ * entries.
+ */
+static _WDIR*
+_wopendir(
+    const wchar_t *dirname)
+{
+    _WDIR *dirp = NULL;
+    int error;
+
+    /* Must have directory name */
+    if (dirname == NULL  ||  dirname[0] == '\0') {
+        dirent_set_errno (ENOENT);
+        return NULL;
+    }
+
+    /* Allocate new _WDIR structure */
+    dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
+    if (dirp != NULL) {
+        DWORD n;
+
+        /* Reset _WDIR structure */
+        dirp->handle = INVALID_HANDLE_VALUE;
+        dirp->patt = NULL;
+        dirp->cached = 0;
+
+        /* Compute the length of full path plus zero terminator
+         * 
+         * Note that on WinRT there's no way to convert relative paths
+         * into absolute paths, so just assume its an absolute path.
+         */
+#       if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+            n = wcslen(dirname);
+#       else
+            n = GetFullPathNameW (dirname, 0, NULL, NULL);
+#       endif
+
+        /* Allocate room for absolute directory name and search pattern */
+        dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
+        if (dirp->patt) {
+
+            /*
+             * Convert relative directory name to an absolute one.  This
+             * allows rewinddir() to function correctly even when current
+             * working directory is changed between opendir() and rewinddir().
+             * 
+             * Note that on WinRT there's no way to convert relative paths
+             * into absolute paths, so just assume its an absolute path.
+             */
+#           if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+                wcsncpy_s(dirp->patt, n+1, dirname, n);
+#           else
+                n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
+#           endif
+            if (n > 0) {
+                wchar_t *p;
+
+                /* Append search pattern \* to the directory name */
+                p = dirp->patt + n;
+                if (dirp->patt < p) {
+                    switch (p[-1]) {
+                    case '\\':
+                    case '/':
+                    case ':':
+                        /* Directory ends in path separator, e.g. c:\temp\ */
+                        /*NOP*/;
+                        break;
+
+                    default:
+                        /* Directory name doesn't end in path separator */
+                        *p++ = '\\';
+                    }
+                }
+                *p++ = '*';
+                *p = '\0';
+
+                /* Open directory stream and retrieve the first entry */
+                if (dirent_first (dirp)) {
+                    /* Directory stream opened successfully */
+                    error = 0;
+                } else {
+                    /* Cannot retrieve first entry */
+                    error = 1;
+                    dirent_set_errno (ENOENT);
+                }
+
+            } else {
+                /* Cannot retrieve full path name */
+                dirent_set_errno (ENOENT);
+                error = 1;
+            }
+
+        } else {
+            /* Cannot allocate memory for search pattern */
+            error = 1;
+        }
+
+    } else {
+        /* Cannot allocate _WDIR structure */
+        error = 1;
+    }
+
+    /* Clean up in case of error */
+    if (error  &&  dirp) {
+        _wclosedir (dirp);
+        dirp = NULL;
+    }
+
+    return dirp;
+}
+
+/*
+ * Read next directory entry.  The directory entry is returned in dirent
+ * structure in the d_name field.  Individual directory entries returned by
+ * this function include regular files, sub-directories, pseudo-directories
+ * "." and ".." as well as volume labels, hidden files and system files.
+ */
+static struct _wdirent*
+_wreaddir(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *datap;
+    struct _wdirent *entp;
+
+    /* Read next directory entry */
+    datap = dirent_next (dirp);
+    if (datap) {
+        size_t n;
+        DWORD attr;
+        
+        /* Pointer to directory entry to return */
+        entp = &dirp->ent;
+
+        /* 
+         * Copy file name as wide-character string.  If the file name is too
+         * long to fit in to the destination buffer, then truncate file name
+         * to PATH_MAX characters and zero-terminate the buffer.
+         */
+        n = 0;
+        while (n + 1 < PATH_MAX  &&  datap->cFileName[n] != 0) {
+            entp->d_name[n] = datap->cFileName[n];
+            n++;
+        }
+        dirp->ent.d_name[n] = 0;
+
+        /* Length of file name excluding zero terminator */
+        entp->d_namlen = n;
+
+        /* File type */
+        attr = datap->dwFileAttributes;
+        if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+            entp->d_type = DT_CHR;
+        } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+            entp->d_type = DT_DIR;
+        } else {
+            entp->d_type = DT_REG;
+        }
+
+        /* Reset dummy fields */
+        entp->d_ino = 0;
+        entp->d_reclen = sizeof (struct _wdirent);
+
+    } else {
+
+        /* Last directory entry read */
+        entp = NULL;
+
+    }
+
+    return entp;
+}
+
+/*
+ * Close directory stream opened by opendir() function.  This invalidates the
+ * DIR structure as well as any directory entry read previously by
+ * _wreaddir().
+ */
+static int
+_wclosedir(
+    _WDIR *dirp)
+{
+    int ok;
+    if (dirp) {
+
+        /* Release search handle */
+        if (dirp->handle != INVALID_HANDLE_VALUE) {
+            FindClose (dirp->handle);
+            dirp->handle = INVALID_HANDLE_VALUE;
+        }
+
+        /* Release search pattern */
+        if (dirp->patt) {
+            free (dirp->patt);
+            dirp->patt = NULL;
+        }
+
+        /* Release directory structure */
+        free (dirp);
+        ok = /*success*/0;
+
+    } else {
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+    }
+    return ok;
+}
+
+/*
+ * Rewind directory stream such that _wreaddir() returns the very first
+ * file name again.
+ */
+static void
+_wrewinddir(
+    _WDIR* dirp)
+{
+    if (dirp) {
+        /* Release existing search handle */
+        if (dirp->handle != INVALID_HANDLE_VALUE) {
+            FindClose (dirp->handle);
+        }
+
+        /* Open new search handle */
+        dirent_first (dirp);
+    }
+}
+
+/* Get first directory entry (internal) */
+static WIN32_FIND_DATAW*
+dirent_first(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *datap;
+
+    /* Open directory and retrieve the first entry */
+    dirp->handle = FindFirstFileExW(
+        dirp->patt, FindExInfoStandard, &dirp->data,
+        FindExSearchNameMatch, NULL, 0);
+    if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* a directory entry is now waiting in memory */
+        datap = &dirp->data;
+        dirp->cached = 1;
+
+    } else {
+
+        /* Failed to re-open directory: no directory entry in memory */
+        dirp->cached = 0;
+        datap = NULL;
+
+    }
+    return datap;
+}
+
+/* Get next directory entry (internal) */
+static WIN32_FIND_DATAW*
+dirent_next(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *p;
+
+    /* Get next directory entry */
+    if (dirp->cached != 0) {
+
+        /* A valid directory entry already in memory */
+        p = &dirp->data;
+        dirp->cached = 0;
+
+    } else if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* Get the next directory entry from stream */
+        if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
+            /* Got a file */
+            p = &dirp->data;
+        } else {
+            /* The very last entry has been processed or an error occured */
+            FindClose (dirp->handle);
+            dirp->handle = INVALID_HANDLE_VALUE;
+            p = NULL;
+        }
+
+    } else {
+
+        /* End of directory stream reached */
+        p = NULL;
+
+    }
+
+    return p;
+}
+
+/* 
+ * Open directory stream using plain old C-string.
+ */
+static DIR*
+opendir(
+    const char *dirname) 
+{
+    struct DIR *dirp;
+    int error;
+
+    /* Must have directory name */
+    if (dirname == NULL  ||  dirname[0] == '\0') {
+        dirent_set_errno (ENOENT);
+        return NULL;
+    }
+
+    /* Allocate memory for DIR structure */
+    dirp = (DIR*) malloc (sizeof (struct DIR));
+    if (dirp) {
+        wchar_t wname[PATH_MAX];
+        size_t n;
+
+        /* Convert directory name to wide-character string */
+        error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
+        if (!error) {
+
+            /* Open directory stream using wide-character name */
+            dirp->wdirp = _wopendir (wname);
+            if (dirp->wdirp) {
+                /* Directory stream opened */
+                error = 0;
+            } else {
+                /* Failed to open directory stream */
+                error = 1;
+            }
+
+        } else {
+            /* 
+             * Cannot convert file name to wide-character string.  This
+             * occurs if the string contains invalid multi-byte sequences or
+             * the output buffer is too small to contain the resulting
+             * string.
+             */
+            error = 1;
+        }
+
+    } else {
+        /* Cannot allocate DIR structure */
+        error = 1;
+    }
+
+    /* Clean up in case of error */
+    if (error  &&  dirp) {
+        free (dirp);
+        dirp = NULL;
+    }
+
+    return dirp;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * When working with text consoles, please note that file names returned by
+ * readdir() are represented in the default ANSI code page while any output to
+ * console is typically formatted on another code page.  Thus, non-ASCII
+ * characters in file names will not usually display correctly on console.  The
+ * problem can be fixed in two ways: (1) change the character set of console
+ * to 1252 using chcp utility and use Lucida Console font, or (2) use
+ * _cprintf function when writing to console.  The _cprinf() will re-encode
+ * ANSI strings to the console code page so many non-ASCII characters will
+ * display correcly.
+ */
+static struct dirent*
+readdir(
+    DIR *dirp) 
+{
+    WIN32_FIND_DATAW *datap;
+    struct dirent *entp;
+
+    /* Read next directory entry */
+    datap = dirent_next (dirp->wdirp);
+    if (datap) {
+        size_t n;
+        int error;
+
+        /* Attempt to convert file name to multi-byte string */
+        error = dirent_wcstombs_s(
+            &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
+
+        /* 
+         * If the file name cannot be represented by a multi-byte string,
+         * then attempt to use old 8+3 file name.  This allows traditional
+         * Unix-code to access some file names despite of unicode
+         * characters, although file names may seem unfamiliar to the user.
+         *
+         * Be ware that the code below cannot come up with a short file
+         * name unless the file system provides one.  At least
+         * VirtualBox shared folders fail to do this.
+         */
+        if (error  &&  datap->cAlternateFileName[0] != '\0') {
+            error = dirent_wcstombs_s(
+                &n, dirp->ent.d_name, PATH_MAX, 
+                datap->cAlternateFileName, PATH_MAX);
+        }
+
+        if (!error) {
+            DWORD attr;
+
+            /* Initialize directory entry for return */
+            entp = &dirp->ent;
+
+            /* Length of file name excluding zero terminator */
+            entp->d_namlen = n - 1;
+
+            /* File attributes */
+            attr = datap->dwFileAttributes;
+            if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+                entp->d_type = DT_CHR;
+            } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+                entp->d_type = DT_DIR;
+            } else {
+                entp->d_type = DT_REG;
+            }
+
+            /* Reset dummy fields */
+            entp->d_ino = 0;
+            entp->d_reclen = sizeof (struct dirent);
+
+        } else {
+            /* 
+             * Cannot convert file name to multi-byte string so construct
+             * an errornous directory entry and return that.  Note that
+             * we cannot return NULL as that would stop the processing
+             * of directory entries completely.
+             */
+            entp = &dirp->ent;
+            entp->d_name[0] = '?';
+            entp->d_name[1] = '\0';
+            entp->d_namlen = 1;
+            entp->d_type = DT_UNKNOWN;
+            entp->d_ino = 0;
+            entp->d_reclen = 0;
+        }
+
+    } else {
+        /* No more directory entries */
+        entp = NULL;
+    }
+
+    return entp;
+}
+
+/*
+ * Close directory stream.
+ */
+static int
+closedir(
+    DIR *dirp) 
+{
+    int ok;
+    if (dirp) {
+
+        /* Close wide-character directory stream */
+        ok = _wclosedir (dirp->wdirp);
+        dirp->wdirp = NULL;
+
+        /* Release multi-byte character version */
+        free (dirp);
+
+    } else {
+
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+
+    }
+    return ok;
+}
+
+/*
+ * Rewind directory stream to beginning.
+ */
+static void
+rewinddir(
+    DIR* dirp) 
+{
+    /* Rewind wide-character string directory stream */
+    _wrewinddir (dirp->wdirp);
+}
+
+/* Convert multi-byte string to wide character string */
+static int
+dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to wide-character string (or count characters) */
+    n = mbstowcs (wcstr, mbstr, sizeInWords);
+    if (!wcstr  ||  n < count) {
+
+        /* Zero-terminate output buffer */
+        if (wcstr  &&  sizeInWords) {
+            if (n >= sizeInWords) {
+                n = sizeInWords - 1;
+            }
+            wcstr[n] = 0;
+        }
+
+        /* Length of resuting multi-byte string WITH zero terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Could not convert string */
+        error = 1;
+
+    }
+
+#endif
+
+    return error;
+}
+
+/* Convert wide-character string to multi-byte string */
+static int
+dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes, /* max size of mbstr */
+    const wchar_t *wcstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to multi-byte string (or count the number of bytes needed) */
+    n = wcstombs (mbstr, wcstr, sizeInBytes);
+    if (!mbstr  ||  n < count) {
+
+        /* Zero-terminate output buffer */
+        if (mbstr  &&  sizeInBytes) {
+            if (n >= sizeInBytes) {
+                n = sizeInBytes - 1;
+            }
+            mbstr[n] = '\0';
+        }
+
+        /* Length of resulting multi-bytes string WITH zero-terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Cannot convert string */
+        error = 1;
+
+    }
+
+#endif
+
+    return error;
+}
+
+/* Set errno variable */
+static void
+dirent_set_errno(
+    int error)
+{
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 and later */
+    _set_errno (error);
+
+#else
+
+    /* Non-Microsoft compiler or older Microsoft compiler */
+    errno = error;
+
+#endif
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*DIRENT_H*/
+
diff --git a/win32_msvc/getopt.h b/win32_msvc/getopt.h
new file mode 100644
index 0000000..df090c8
--- /dev/null
+++ b/win32_msvc/getopt.h
@@ -0,0 +1,372 @@
+/* -*- indent-tabs-mode: nil -*-
+ *
+ * ya_getopt  - Yet another getopt
+ * https://github.com/kubo/ya_getopt
+ *
+ * Copyright 2015 Kubo Takehiro <kubo@jiubao.org>
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of the authors.
+ *
+ */
+
+
+#ifndef YA_GETOPT_H
+#define YA_GETOPT_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ya_no_argument        0
+#define ya_required_argument  1
+#define ya_optional_argument  2
+
+struct option {
+    const char *name;
+    int has_arg;
+    int *flag;
+    int val;
+};
+
+//  error: ‘ya_getopt’ defined but not used [-Werror=unused-function]
+///static int ya_getopt(int argc, char * const argv[], const char *optstring);
+static int ya_getopt_long(int argc, char * const argv[], const char *optstring,
+                   const struct option *longopts, int *longindex);
+///static int ya_getopt_long_only(int argc, char * const argv[], const char *optstring,
+///                        const struct option *longopts, int *longindex);
+
+#ifndef YA_GETOPT_NO_COMPAT_MACRO
+///#define getopt ya_getopt
+#define getopt_long ya_getopt_long
+///#define getopt_long_only ya_getopt_long_only
+#define optarg ya_optarg
+#define optind ya_optind
+#define opterr ya_opterr
+#define optopt ya_optopt
+#define no_argument ya_no_argument
+#define required_argument ya_required_argument
+#define optional_argument ya_optional_argument
+#endif
+
+
+// ===============================================================================
+
+char *ya_optarg = NULL;
+int ya_optind = 1;
+int ya_opterr = 1;
+int ya_optopt = '?';
+
+static char *ya_optnext = NULL;
+static int posixly_correct = -1;
+static int handle_nonopt_argv = 0;
+
+static void ya_getopt_error(const char *optstring, const char *format, ...);
+static void check_gnu_extension(const char *optstring);
+static int ya_getopt_internal(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex, int long_only);
+static int ya_getopt_shortopts(int argc, char * const argv[], const char *optstring, int long_only);
+static int ya_getopt_longopts(int argc, char * const argv[], char *arg, const char *optstring, const struct option *longopts, int *longindex, int *long_only_flag);
+
+static void ya_getopt_error(const char *optstring, const char *format, ...)
+{
+    if (ya_opterr && optstring[0] != ':') {
+        va_list ap;
+        va_start(ap, format);
+        vfprintf(stderr, format, ap);
+        va_end(ap);
+    }
+}
+
+static void check_gnu_extension(const char *optstring)
+{
+    if (optstring[0] == '+' || getenv("POSIXLY_CORRECT") != NULL) {
+        posixly_correct = 1;
+    } else {
+        posixly_correct = 0;
+    }
+    if (optstring[0] == '-') {
+        handle_nonopt_argv = 1;
+    } else {
+        handle_nonopt_argv = 0;
+    }
+}
+
+static int is_option(const char *arg)
+{
+    return arg[0] == '-' && arg[1] != '\0';
+}
+
+// ==================================================================
+
+///static int ya_getopt(int argc, char * const argv[], const char *optstring)
+///{
+///    return ya_getopt_internal(argc, argv, optstring, NULL, NULL, 0);
+///}
+
+static int ya_getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex)
+{
+    return ya_getopt_internal(argc, argv, optstring, longopts, longindex, 0);
+}
+
+///static int ya_getopt_long_only(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex)
+///{
+///    return ya_getopt_internal(argc, argv, optstring, longopts, longindex, 1);
+///}
+
+// ==================================================================
+
+static int ya_getopt_internal(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex, int long_only)
+{
+    static int start, end;
+
+    if (ya_optopt == '?') {
+        ya_optopt = 0;
+    }
+
+    if (posixly_correct == -1) {
+        check_gnu_extension(optstring);
+    }
+
+    if (ya_optind == 0) {
+        check_gnu_extension(optstring);
+        ya_optind = 1;
+        ya_optnext = NULL;
+    }
+
+    switch (optstring[0]) {
+    case '+':
+    case '-':
+        optstring++;
+    }
+
+    if (ya_optnext == NULL && start != 0) {
+        int last_pos = ya_optind - 1;
+
+        ya_optind -= end - start;
+        if (ya_optind <= 0) {
+            ya_optind = 1;
+        }
+        while (start < end--) {
+            int i;
+            char *arg = argv[end];
+
+            for (i = end; i < last_pos; i++) {
+                ((char **)argv)[i] = argv[i + 1];
+            }
+            ((char const **)argv)[i] = arg;
+            last_pos--;
+        }
+        start = 0;
+    }
+
+    if (ya_optind >= argc) {
+        ya_optarg = NULL;
+        return -1;
+    }
+    if (ya_optnext == NULL) {
+        const char *arg = argv[ya_optind];
+        if (!is_option(arg)) {
+            if (handle_nonopt_argv) {
+                ya_optarg = argv[ya_optind++];
+                start = 0;
+                return 1;
+            } else if (posixly_correct) {
+                ya_optarg = NULL;
+                return -1;
+            } else {
+                int i;
+
+                start = ya_optind;
+                for (i = ya_optind + 1; i < argc; i++) {
+                    if (is_option(argv[i])) {
+                        end = i;
+                        break;
+                    }
+                }
+                if (i == argc) {
+                    ya_optarg = NULL;
+                    return -1;
+                }
+                ya_optind = i;
+                arg = argv[ya_optind];
+            }
+        }
+        if (strcmp(arg, "--") == 0) {
+            ya_optind++;
+            return -1;
+        }
+        if (longopts != NULL && arg[1] == '-') {
+            return ya_getopt_longopts(argc, argv, argv[ya_optind] + 2, optstring, longopts, longindex, NULL);
+        }
+    }
+
+    if (ya_optnext == NULL) {
+        ya_optnext = argv[ya_optind] + 1;
+    }
+    if (long_only) {
+        int long_only_flag = 0;
+        int rv = ya_getopt_longopts(argc, argv, ya_optnext, optstring, longopts, longindex, &long_only_flag);
+        if (!long_only_flag) {
+            ya_optnext = NULL;
+            return rv;
+        }
+    }
+
+    return ya_getopt_shortopts(argc, argv, optstring, long_only);
+}
+
+static int ya_getopt_shortopts(int argc, char * const argv[], const char *optstring, int long_only)
+{
+    int opt = *ya_optnext;
+    const char *os = strchr(optstring, opt);
+
+    if (os == NULL) {
+        ya_optarg = NULL;
+        if (long_only) {
+            ya_getopt_error(optstring, "%s: unrecognized option '-%s'\n", argv[0], ya_optnext);
+            ya_optind++;
+            ya_optnext = NULL;
+        } else {
+            ya_optopt = opt;
+            ya_getopt_error(optstring, "%s: invalid option -- '%c'\n", argv[0], opt);
+            if (*(++ya_optnext) == 0) {
+                ya_optind++;
+                ya_optnext = NULL;
+            }
+        }
+        return '?';
+    }
+    if (os[1] == ':') {
+        if (ya_optnext[1] == 0) {
+            ya_optind++;
+            ya_optnext = NULL;
+            if (os[2] == ':') {
+                /* optional argument */
+                ya_optarg = NULL;
+            } else {
+                if (ya_optind == argc) {
+                    ya_optarg = NULL;
+                    ya_optopt = opt;
+                    ya_getopt_error(optstring, "%s: option requires an argument -- '%c'\n", argv[0], opt);
+                    if (optstring[0] == ':') {
+                        return ':';
+                    } else {
+                        return '?';
+                    }
+                }
+                ya_optarg = argv[ya_optind];
+                ya_optind++;
+            }
+        } else {
+            ya_optarg = ya_optnext + 1;
+            ya_optind++;
+        }
+        ya_optnext = NULL;
+    } else {
+        ya_optarg = NULL;
+        if (ya_optnext[1] == 0) {
+            ya_optnext = NULL;
+            ya_optind++;
+        } else {
+            ya_optnext++;
+        }
+    }
+    return opt;
+}
+
+static int ya_getopt_longopts(int argc, char * const argv[], char *arg, const char *optstring, const struct option *longopts, int *longindex, int *long_only_flag)
+{
+    char *val = NULL;
+    const struct option *opt;
+    size_t namelen;
+    int idx;
+
+    for (idx = 0; longopts[idx].name != NULL; idx++) {
+        opt = &longopts[idx];
+        namelen = strlen(opt->name);
+        if (strncmp(arg, opt->name, namelen) == 0) {
+            switch (arg[namelen]) {
+            case '\0':
+                switch (opt->has_arg) {
+                case ya_required_argument:
+                    ya_optind++;
+                    if (ya_optind == argc) {
+                        ya_optarg = NULL;
+                        ya_optopt = opt->val;
+                        ya_getopt_error(optstring, "%s: option '--%s' requires an argument\n", argv[0], opt->name);
+                        if (optstring[0] == ':') {
+                            return ':';
+                        } else {
+                            return '?';
+                        }
+                    }
+                    val = argv[ya_optind];
+                    break;
+                }
+                goto found;
+            case '=':
+                if (opt->has_arg == ya_no_argument) {
+                    const char *hyphens = (argv[ya_optind][1] == '-') ? "--" : "-";
+
+                    ya_optind++;
+                    ya_optarg = NULL;
+                    ya_optopt = opt->val;
+                    ya_getopt_error(optstring, "%s: option '%s%s' doesn't allow an argument\n", argv[0], hyphens, opt->name);
+                    return '?';
+                }
+                val = arg + namelen + 1;
+                goto found;
+            }
+        }
+    }
+    if (long_only_flag) {
+        *long_only_flag = 1;
+    } else {
+        ya_getopt_error(optstring, "%s: unrecognized option '%s'\n", argv[0], argv[ya_optind]);
+        ya_optind++;
+    }
+    return '?';
+found:
+    ya_optarg = val;
+    ya_optind++;
+    if (opt->flag) {
+        *opt->flag = opt->val;
+    }
+    if (longindex) {
+        *longindex = idx;
+    }
+    return opt->flag ? 0 : opt->val;
+}
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/win32_msvc/unistd.h b/win32_msvc/unistd.h
new file mode 100644
index 0000000..51d57b5
--- /dev/null
+++ b/win32_msvc/unistd.h
@@ -0,0 +1,42 @@
+#ifndef _UNISTD_H
+#define _UNISTD_H    1
+
+/* This file intended to serve as a drop-in replacement for 
+ *  unistd.h on Windows
+ *  Please add functionality as neeeded 
+ */
+
+#include <stdlib.h>
+#include <io.h>
+#include <process.h> /* for getpid() and the exec..() family */
+#include <direct.h> /* for _getcwd() and _chdir() */
+
+#define srandom srand
+#define random rand
+
+/* Values for the second argument to access.
+   These may be OR'd together.  */
+#define R_OK    4       /* Test for read permission.  */
+#define W_OK    2       /* Test for write permission.  */
+//#define   X_OK    1       /* execute permission - unsupported in windows*/
+#define F_OK    0       /* Test for existence.  */
+
+#define access _access
+#define dup2 _dup2
+#define execve _execve
+#define ftruncate _chsize
+#define unlink _unlink
+#define fileno _fileno
+#define getcwd _getcwd
+#define chdir _chdir
+#define isatty _isatty
+#define lseek _lseek
+/* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */
+
+#define ssize_t int
+
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+#endif /* unistd.h  */

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/lib/debug/.build-id/37/c85f8bdfdb48b20751428c447d59257c07b22c.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/88/ef478d79afd3f2e66e42bed1f3f48b63fd3471.debug

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/debug/.build-id/15/02458ab607425f3ad8d3bc41bb76e877417e5b.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/98/09243c701b9bb871e52b938b5dcff5682671f0.debug

No differences were encountered between the control files of package libunshield-dev

No differences were encountered between the control files of package libunshield0

Control files of package libunshield0-dbgsym: lines which differ (wdiff format)

  • Build-Ids: 1502458ab607425f3ad8d3bc41bb76e877417e5b 88ef478d79afd3f2e66e42bed1f3f48b63fd3471

Control files of package unshield: lines which differ (wdiff format)

  • Depends: libc6 (>= 2.34), 2.33), libunshield0 (>= 1.4)

Control files of package unshield-dbgsym: lines which differ (wdiff format)

  • Build-Ids: 9809243c701b9bb871e52b938b5dcff5682671f0 37c85f8bdfdb48b20751428c447d59257c07b22c

More details

Full run details