Merge branch 'FindBoost-1.64-deps' into release
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index bb34de5..c41a986 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -269,7 +269,13 @@
       set(id_toolset "")
     endif()
     if("${lang}" STREQUAL "Swift")
-      set(id_lang_version "SWIFT_VERSION = 2.3;")
+      if(CMAKE_Swift_LANGUAGE_VERSION)
+        set(id_lang_version "SWIFT_VERSION = ${CMAKE_Swift_LANGUAGE_VERSION};")
+      elseif(XCODE_VERSION VERSION_GREATER_EQUAL 8.3)
+        set(id_lang_version "SWIFT_VERSION = 3.0;")
+      else()
+        set(id_lang_version "SWIFT_VERSION = 2.3;")
+      endif()
     else()
       set(id_lang_version "")
     endif()
diff --git a/Modules/CMakeRCInformation.cmake b/Modules/CMakeRCInformation.cmake
index 10f2cfb..7ddd297 100644
--- a/Modules/CMakeRCInformation.cmake
+++ b/Modules/CMakeRCInformation.cmake
@@ -17,11 +17,26 @@
   ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake)
 include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL)
 
-string(STRIP "$ENV{RCFLAGS} ${CMAKE_RC_FLAGS_INIT}" CMAKE_RC_FLAGS_INIT)
+set(CMAKE_RC_FLAGS_INIT "$ENV{RCFLAGS} ${CMAKE_RC_FLAGS_INIT}")
+
+foreach(c "" _DEBUG _RELEASE _MINSIZEREL _RELWITHDEBINFO)
+  string(STRIP "${CMAKE_RC_FLAGS${c}_INIT}" CMAKE_RC_FLAGS${c}_INIT)
+endforeach()
 
 set (CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS_INIT}" CACHE STRING
      "Flags for Windows Resource Compiler.")
 
+if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
+  set (CMAKE_RC_FLAGS_DEBUG "${CMAKE_RC_FLAGS_DEBUG_INIT}" CACHE STRING
+    "Flags for Windows Resource Compiler during debug builds.")
+  set (CMAKE_RC_FLAGS_MINSIZEREL "${CMAKE_RC_FLAGS_MINSIZEREL_INIT}" CACHE STRING
+    "Flags for Windows Resource Compiler during release builds for minimum size.")
+  set (CMAKE_RC_FLAGS_RELEASE "${CMAKE_RC_FLAGS_RELEASE_INIT}" CACHE STRING
+    "Flags for Windows Resource Compiler during release builds.")
+  set (CMAKE_RC_FLAGS_RELWITHDEBINFO "${CMAKE_RC_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING
+    "Flags for Windows Resource Compiler during release builds with debug info.")
+endif()
+
 # These are the only types of flags that should be passed to the rc
 # command, if COMPILE_FLAGS is used on a target this will be used
 # to filter out any other flags
diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake
index 87fa9dd..e905bc6 100644
--- a/Modules/CPackRPM.cmake
+++ b/Modules/CPackRPM.cmake
@@ -721,14 +721,6 @@
 # Debuginfo packages contain debug symbols and sources for debugging packaged
 # binaries.
 #
-# .. note::
-#
-#  Currently multiple debuginfo packages are generated if component based
-#  packaging is used - one debuginfo package per component. This duplicates
-#  sources if multiple binaries are using them. This is a side effect of
-#  how CPackRPM currently generates component packages and will be addressed
-#  in later versions of the generator.
-#
 # Debuginfo RPM packaging has it's own set of variables:
 #
 # .. variable:: CPACK_RPM_DEBUGINFO_PACKAGE
diff --git a/Modules/Compiler/SDCC-C-DetermineCompiler.cmake b/Modules/Compiler/SDCC-C-DetermineCompiler.cmake
index 1d7dd78..4c70c5e 100644
--- a/Modules/Compiler/SDCC-C-DetermineCompiler.cmake
+++ b/Modules/Compiler/SDCC-C-DetermineCompiler.cmake
@@ -1,10 +1,16 @@
 
 # sdcc, the small devices C compiler for embedded systems,
 #   http://sdcc.sourceforge.net  */
-set(_compiler_id_pp_test "defined(SDCC)")
+set(_compiler_id_pp_test "defined(__SDCC_VERSION_MAJOR) || defined(SDCC)")
 
 set(_compiler_id_version_compute "
+# if defined(__SDCC_VERSION_MAJOR)
+#  define COMPILER_VERSION_MAJOR @MACRO_DEC@(__SDCC_VERSION_MAJOR)
+#  define COMPILER_VERSION_MINOR @MACRO_DEC@(__SDCC_VERSION_MINOR)
+#  define COMPILER_VERSION_PATCH @MACRO_DEC@(__SDCC_VERSION_PATCH)
+# else
   /* SDCC = VRP */
 #  define COMPILER_VERSION_MAJOR @MACRO_DEC@(SDCC/100)
 #  define COMPILER_VERSION_MINOR @MACRO_DEC@(SDCC/10 % 10)
-#  define COMPILER_VERSION_PATCH @MACRO_DEC@(SDCC    % 10)")
+#  define COMPILER_VERSION_PATCH @MACRO_DEC@(SDCC    % 10)
+# endif")
diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake
index 1061da0..a3478a3 100644
--- a/Modules/InstallRequiredSystemLibraries.cmake
+++ b/Modules/InstallRequiredSystemLibraries.cmake
@@ -191,19 +191,31 @@
     set(vs "${_MSVCRT_IDE_VERSION}")
 
     # Find the runtime library redistribution directory.
-    get_filename_component(msvc_install_dir
-      "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${vs}.0;InstallDir]" ABSOLUTE)
-    set(programfilesx86 "ProgramFiles(x86)")
     if(vs VERSION_LESS 15 AND DEFINED MSVC${vs}_REDIST_DIR AND EXISTS "${MSVC${vs}_REDIST_DIR}")
       set(MSVC_REDIST_DIR "${MSVC${vs}_REDIST_DIR}") # use old cache entry
     endif()
-    find_path(MSVC_REDIST_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.VC${vs}0.CRT
-      PATHS
-        "${msvc_install_dir}/../../VC/redist"
+    if(NOT vs VERSION_LESS 15)
+      set(_vs_redist_paths "")
+      cmake_host_system_information(RESULT _vs_dir QUERY VS_${vs}_DIR) # undocumented query
+      if(IS_DIRECTORY "${_vs_dir}")
+        file(GLOB _vs_redist_paths "${_vs_dir}/VC/Redist/MSVC/*")
+      endif()
+      unset(_vs_dir)
+    else()
+      get_filename_component(_vs_dir
+        "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${vs}.0;InstallDir]" ABSOLUTE)
+      set(programfilesx86 "ProgramFiles(x86)")
+      set(_vs_redist_paths
+        "${_vs_dir}/../../VC/redist"
         "${base_dir}/VC/redist"
         "$ENV{ProgramFiles}/Microsoft Visual Studio ${vs}.0/VC/redist"
         "$ENV{${programfilesx86}}/Microsoft Visual Studio ${vs}.0/VC/redist"
-      )
+        )
+      unset(_vs_dir)
+      unset(programfilesx86)
+    endif()
+    find_path(MSVC_REDIST_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.VC${vs}0.CRT PATHS ${_vs_redist_paths})
+    unset(_vs_redist_paths)
     mark_as_advanced(MSVC_REDIST_DIR)
     set(MSVC_CRT_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC${vs}0.CRT")
 
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index 31b26b59..e4aca6e 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -310,6 +310,9 @@
   if(NOT CMAKE_RC_FLAGS_INIT)
     string(APPEND CMAKE_RC_FLAGS_INIT " ${_PLATFORM_DEFINES} ${_PLATFORM_DEFINES_${lang}}")
   endif()
+  if(NOT CMAKE_RC_FLAGS_DEBUG_INIT)
+    string(APPEND CMAKE_RC_FLAGS_DEBUG_INIT " /D_DEBUG")
+  endif()
 
   enable_language(RC)
   set(CMAKE_NINJA_CMCLDEPS_RC 1)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index e2b8d4f..8ae8b33 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -2,4 +2,4 @@
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 8)
 set(CMake_VERSION_PATCH 0)
-set(CMake_VERSION_RC 2)
+set(CMake_VERSION_RC 3)
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 7da93ac..e135ac6 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -7,6 +7,12 @@
 #include "cmMakefile.h"
 #include "cmsys/SystemInformation.hxx"
 
+#if defined(_WIN32)
+#include "cmSystemTools.h"
+#include "cmVSSetupHelper.h"
+#define HAVE_VS_SETUP_HELPER
+#endif
+
 class cmExecutionStatus;
 
 // cmCMakeHostSystemInformation
@@ -70,6 +76,13 @@
     value = this->ValueToString(info.GetTotalPhysicalMemory());
   } else if (key == "AVAILABLE_PHYSICAL_MEMORY") {
     value = this->ValueToString(info.GetAvailablePhysicalMemory());
+#ifdef HAVE_VS_SETUP_HELPER
+  } else if (key == "VS_15_DIR") {
+    cmVSSetupAPIHelper vsSetupAPIHelper;
+    if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
+      cmSystemTools::ConvertToUnixSlashes(value);
+    }
+#endif
   } else {
     std::string e = "does not recognize <key> " + key;
     this->SetError(e);
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 8627cf2..dd771b1 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -3075,10 +3075,14 @@
                                 this->CreateString(this->GeneratorToolset));
   }
   if (this->GetLanguageEnabled("Swift")) {
-    std::string swiftVersion = "2.3";
+    std::string swiftVersion;
     if (const char* vers = this->CurrentMakefile->GetDefinition(
           "CMAKE_Swift_LANGUAGE_VERSION")) {
       swiftVersion = vers;
+    } else if (this->XcodeVersion >= 83) {
+      swiftVersion = "3.0";
+    } else {
+      swiftVersion = "2.3";
     }
     buildSettings->AddAttribute("SWIFT_VERSION",
                                 this->CreateString(swiftVersion));
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index c6c0e05..8d07776 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -148,6 +148,11 @@
   this->Defines.insert(this->Defines.end(), defines.begin(), defines.end());
 }
 
+std::vector<std::string> const& cmIDEOptions::GetDefines() const
+{
+  return this->Defines;
+}
+
 void cmIDEOptions::AddFlag(const char* flag, const char* value)
 {
   this->FlagMap[flag] = value;
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index a0696e1..be2fd6d 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -24,6 +24,8 @@
   void AddDefine(const std::string& define);
   void AddDefines(const char* defines);
   void AddDefines(const std::vector<std::string>& defines);
+  std::vector<std::string> const& GetDefines() const;
+
   void AddFlag(const char* flag, const char* value);
   void AddFlag(const char* flag, std::vector<std::string> const& value);
   void AppendFlag(std::string const& flag, std::string const& value);
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 4fc664d..b1374c2 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -550,10 +550,6 @@
 #ifdef _WIN32
     8000,
 #endif
-#if defined(_SC_ARG_MAX)
-    // for instance ARG_MAX is 2096152 on Ubuntu or 262144 on Mac
-    ((int)sysconf(_SC_ARG_MAX)) - 1000,
-#endif
 #if defined(__linux)
     // #define MAX_ARG_STRLEN (PAGE_SIZE * 32) in Linux's binfmts.h
     ((int)sysconf(_SC_PAGESIZE) * 32) - 1000,
@@ -562,7 +558,15 @@
   };
 
   size_t const arrSz = cmArraySize(limits);
-  int const sz = *std::min_element(limits, limits + arrSz);
+  int sz = *std::min_element(limits, limits + arrSz);
+#if defined(_SC_ARG_MAX)
+  // for instance ARG_MAX is 2096152 on Ubuntu or 262144 on Mac
+  int const szArgMax = static_cast<int>(sysconf(_SC_ARG_MAX));
+  // a return value of -1 signifies an unrestricted value
+  if (szArgMax != -1) {
+    sz = std::min(sz, szArgMax - 1000);
+  }
+#endif
   if (sz == std::numeric_limits<int>::max()) {
     return 0;
   }
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 7447821..902fe03 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2346,6 +2346,11 @@
     std::string(this->Makefile->GetSafeDefinition(rcConfigFlagsVar));
 
   rcOptions.Parse(flags.c_str());
+
+  // For historical reasons, add the C preprocessor defines to RC.
+  Options& clOptions = *(this->ClOptions[configName]);
+  rcOptions.AddDefines(clOptions.GetDefines());
+
   this->RcOptions[configName] = pOptions.release();
   return true;
 }
@@ -2358,12 +2363,9 @@
   }
   this->WriteString("<ResourceCompile>\n", 2);
 
-  // Preprocessor definitions and includes are shared with clOptions.
-  Options& clOptions = *(this->ClOptions[configName]);
-  clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
-                                          "\n", "RC");
-
   Options& rcOptions = *(this->RcOptions[configName]);
+  rcOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
+                                          "\n", "RC");
   rcOptions.AppendFlag("AdditionalIncludeDirectories", includes);
   rcOptions.AppendFlag("AdditionalIncludeDirectories",
                        "%(AdditionalIncludeDirectories)");
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index c0913e6..da6f9a7 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -1,5 +1,6 @@
 #include "cmVisualStudioGeneratorOptions.h"
 
+#include "cmAlgorithms.h"
 #include "cmLocalVisualStudioGenerator.h"
 #include "cmOutputConverter.h"
 #include "cmSystemTools.h"
@@ -267,8 +268,10 @@
     fout << prefix << "PreprocessorDefinitions=\"";
   }
   const char* sep = "";
+  std::vector<std::string>::const_iterator de =
+    cmRemoveDuplicates(this->Defines);
   for (std::vector<std::string>::const_iterator di = this->Defines.begin();
-       di != this->Defines.end(); ++di) {
+       di != de; ++di) {
     // Escape the definition for the compiler.
     std::string define;
     if (this->Version < cmGlobalVisualStudioGenerator::VS10) {
diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
index fc90d09..a5b38fd 100644
--- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
+++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
@@ -205,14 +205,14 @@
 /usr/foo/bar/non_relocatable/depth_two
 /usr/foo/bar/non_relocatable/depth_two/symlink_from_non_relocatable_path
 /usr/foo/bar/other_relocatable
-/usr/foo/bar/other_relocatable/depth_two$")
+/usr/foo/bar/other_relocatable/depth_two(\n.*\.build-id.*)*$")
       elseif(check_file_headers_match)
         set(check_file_match_expected_summary ".*${CPACK_RPM_HEADERS_PACKAGE_SUMMARY}.*")
         set(check_file_match_expected_description ".*${CPACK_RPM_HEADERS_PACKAGE_DESCRIPTION}.*")
         set(check_file_match_expected_relocation_path "Relocations${whitespaces}:${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}")
         set(check_file_match_expected_architecture "noarch")
         set(spec_regex "*headers*")
-        set(check_content_list "^/usr/foo/bar\n/usr/foo/bar/include\n/usr/foo/bar/include/mylib.h$")
+        set(check_content_list "^/usr/foo/bar\n/usr/foo/bar/include\n/usr/foo/bar/include/mylib.h(\n.*\.build-id.*)*$")
       elseif(check_file_applications_match)
         set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*")
         set(check_file_match_expected_description ".*${CPACK_COMPONENT_APPLICATIONS_DESCRIPTION}.*")
@@ -221,7 +221,7 @@
         set(spec_regex "*applications*")
         set(check_content_list "^/usr/foo/bar
 /usr/foo/bar/bin
-/usr/foo/bar/bin/mylibapp$")
+/usr/foo/bar/bin/mylibapp(\n.*\.build-id.*)*$")
       elseif(check_file_Unspecified_match)
         set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*")
         set(check_file_match_expected_description ".*DESCRIPTION.*")
@@ -241,7 +241,7 @@
 /usr/foo/bar/share/man/mylib/man3
 /usr/foo/bar/share/man/mylib/man3/mylib.1
 /usr/foo/bar/share/man/mylib/man3/mylib.1/mylib
-/usr/foo/bar/share/man/mylib/man3/mylib.1/mylib2$")
+/usr/foo/bar/share/man/mylib/man3/mylib.1/mylib2(\n.*\.build-id.*)*$")
       else()
         message(FATAL_ERROR "error: unexpected rpm package '${check_file}'")
       endif()
diff --git a/Tests/RunCMake/CPack/RPM/Helpers.cmake b/Tests/RunCMake/CPack/RPM/Helpers.cmake
index bbc358c8..d8012b1 100644
--- a/Tests/RunCMake/CPack/RPM/Helpers.cmake
+++ b/Tests/RunCMake/CPack/RPM/Helpers.cmake
@@ -36,6 +36,10 @@
           OUTPUT_STRIP_TRAILING_WHITESPACE)
   string(REGEX REPLACE "\n" ";" package_content_ "${package_content_}")
 
+  # never versions of rpmbuild (introduced in rpm 4.13.0.1) add build_id links
+  # to packages - tests should ignore them
+  list(FILTER package_content_ EXCLUDE REGEX ".*\.build-id.*")
+
   set(${RESULT_VAR} "${package_content_}" PARENT_SCOPE)
 endfunction()
 
diff --git a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake
index bc54d79..73d7481 100644
--- a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake
@@ -21,7 +21,9 @@
 set(output_error_message_
     "\n${RPMBUILD_EXECUTABLE} error: '${error_}';\nresult: '${result_}';\n${output_error_message}")
 
-set(EXPECTED_FILE_CONTENT_ "^/foo${whitespaces_}/foo/test_prog$")
+# expected file content are test_prog and optional build-id links that are
+# generated by rpmbuild (introduced in rpm 4.13.0.1)
+set(EXPECTED_FILE_CONTENT_ "^/foo${whitespaces_}/foo/test_prog(${whitespaces_}.*\.build-id.*)*$")
 
 file(GLOB_RECURSE FOUND_FILE_ RELATIVE "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS" "${CMAKE_CURRENT_BINARY_DIR}/test_rpm/RPMS/*.rpm")
 list(APPEND foundFiles_ "${FOUND_FILE_}")
diff --git a/Tests/SwiftMix/ObjCMain.m b/Tests/SwiftMix/ObjCMain.m
index 7fa90ae..20f0bf1 100644
--- a/Tests/SwiftMix/ObjCMain.m
+++ b/Tests/SwiftMix/ObjCMain.m
@@ -1,4 +1,4 @@
 #import "SwiftMix-Swift.h"
 int ObjCMain(int argc, char const* const argv[]) {
-  return [SwiftMainClass SwiftMain:argc argv:argv];
+  return [SwiftMainClass SwiftMain];
 }
diff --git a/Tests/SwiftMix/SwiftMain.swift b/Tests/SwiftMix/SwiftMain.swift
index 3629ac8..a4a0a62 100644
--- a/Tests/SwiftMix/SwiftMain.swift
+++ b/Tests/SwiftMix/SwiftMain.swift
@@ -1,12 +1,8 @@
 import Foundation
 
 @objc class SwiftMainClass : NSObject {
-  class func SwiftMain(argc:Int, argv:UnsafePointer<UnsafePointer<CChar>>) -> Int32 {
-    dump("argc: \(argc)")
-    for (var i = 0; i < argc; ++i) {
-      let argi = String.fromCString(argv[i])
-      dump("arg[\(i)]: \(argi)");
-    }
+  class func SwiftMain() -> Int32 {
+    dump("Hello World!");
     return 0;
   }
 }
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
index c50ba84..8df52c3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
@@ -850,29 +850,33 @@
 		zip_entry->mode |= AE_IFREG;
 	}
 
-	if ((zip_entry->mode & AE_IFMT) == 0) {
-		/* Especially in streaming mode, we can end up
-		   here without having seen proper mode information.
-		   Guess from the filename. */
+	/* If the mode is totally empty, set some sane default. */
+	if (zip_entry->mode == 0) {
+		zip_entry->mode |= 0664;
+	}
+
+	/* Make sure that entries with a trailing '/' are marked as directories
+	 * even if the External File Attributes contains bogus values.  If this
+	 * is not a directory and there is no type, assume regularfile. */
+	if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) {
+		int has_slash;
+
 		wp = archive_entry_pathname_w(entry);
 		if (wp != NULL) {
 			len = wcslen(wp);
-			if (len > 0 && wp[len - 1] == L'/')
-				zip_entry->mode |= AE_IFDIR;
-			else
-				zip_entry->mode |= AE_IFREG;
+			has_slash = len > 0 && wp[len - 1] == L'/';
 		} else {
 			cp = archive_entry_pathname(entry);
 			len = (cp != NULL)?strlen(cp):0;
-			if (len > 0 && cp[len - 1] == '/')
-				zip_entry->mode |= AE_IFDIR;
-			else
-				zip_entry->mode |= AE_IFREG;
+			has_slash = len > 0 && cp[len - 1] == '/';
 		}
-		if (zip_entry->mode == AE_IFDIR) {
-			zip_entry->mode |= 0775;
-		} else if (zip_entry->mode == AE_IFREG) {
-			zip_entry->mode |= 0664;
+		/* Correct file type as needed. */
+		if (has_slash) {
+			zip_entry->mode &= ~AE_IFMT;
+			zip_entry->mode |= AE_IFDIR;
+			zip_entry->mode |= 0111;
+		} else if ((zip_entry->mode & AE_IFMT) == 0) {
+			zip_entry->mode |= AE_IFREG;
 		}
 	}