Răsfoiți Sursa

Update to physfs 3.2.0.

Brucey 2 ani în urmă
părinte
comite
026ccde705
30 a modificat fișierele cu 487 adăugiri și 214 ștergeri
  1. 1 1
      physfs.mod/physfs/.gitignore
  2. 0 6
      physfs.mod/physfs/.hg_archival.txt
  3. 0 17
      physfs.mod/physfs/.hgtags
  4. 105 73
      physfs.mod/physfs/CMakeLists.txt
  5. 16 22
      physfs.mod/physfs/LICENSE.txt
  6. 1 1
      physfs.mod/physfs/docs/CHANGELOG.txt
  7. 3 3
      physfs.mod/physfs/extras/buildbot-checker.sh
  8. 93 0
      physfs.mod/physfs/extras/uninstall.sh
  9. 81 26
      physfs.mod/physfs/src/physfs.c
  10. 4 2
      physfs.mod/physfs/src/physfs.h
  11. 1 1
      physfs.mod/physfs/src/physfs_archiver_7z.c
  12. 1 1
      physfs.mod/physfs/src/physfs_archiver_grp.c
  13. 1 1
      physfs.mod/physfs/src/physfs_archiver_hog.c
  14. 3 2
      physfs.mod/physfs/src/physfs_archiver_iso9660.c
  15. 1 1
      physfs.mod/physfs/src/physfs_archiver_mvl.c
  16. 2 1
      physfs.mod/physfs/src/physfs_archiver_qpak.c
  17. 3 2
      physfs.mod/physfs/src/physfs_archiver_slb.c
  18. 2 2
      physfs.mod/physfs/src/physfs_archiver_unpacked.c
  19. 2 1
      physfs.mod/physfs/src/physfs_archiver_vdf.c
  20. 1 1
      physfs.mod/physfs/src/physfs_archiver_wad.c
  21. 12 4
      physfs.mod/physfs/src/physfs_archiver_zip.c
  22. 57 10
      physfs.mod/physfs/src/physfs_internal.h
  23. 3 0
      physfs.mod/physfs/src/physfs_lzmasdk.h
  24. 13 5
      physfs.mod/physfs/src/physfs_miniz.h
  25. 19 6
      physfs.mod/physfs/src/physfs_platform_apple.m
  26. 4 4
      physfs.mod/physfs/src/physfs_platform_os2.c
  27. 40 8
      physfs.mod/physfs/src/physfs_platform_posix.c
  28. 5 5
      physfs.mod/physfs/src/physfs_platform_windows.c
  29. 12 7
      physfs.mod/physfs/src/physfs_unicode.c
  30. 1 1
      physfs.mod/physfs/test/test_physfs.c

+ 1 - 1
physfs.mod/physfs/.hgignore → physfs.mod/physfs/.gitignore

@@ -1,2 +1,2 @@
-syntax:glob
 cmake-build
+

+ 0 - 6
physfs.mod/physfs/.hg_archival.txt

@@ -1,6 +0,0 @@
-repo: 7672c9962ce627edaaa67ff54fe4ad8f9a46dc2b
-node: acdcf93d1f9b83e10728386354004f893d560d3b
-branch: default
-latesttag: release-3.0.0
-latesttagdistance: 45
-changessincelatesttag: 45

+ 0 - 17
physfs.mod/physfs/.hgtags

@@ -1,17 +0,0 @@
-0bb92a5f0fffd2452cc737346e8b796c213a5688 release-0.1.1
-2f2afcbd8abd784f738ac45b0368044763d63748 release-0.1.0
-3c7cf50a58fbf220154acd4bdfdf00a21f259eb7 release-0.1.8
-473b50402f55b2340fc286775d1b78d18a810362 release-0.1.3
-60b5f566a2585d78b2ffadd8d9c16299d0340820 release-1.0.0
-67aff4091bf129f7167ed87f937b15f31093e19e release-0.1.9
-6ad1722bbcaec1265cb74c9b7be13fe02a547d37 release-0.1.7
-8f3ccaaea1cd5dc19235882494d6102e5e9176fb release-0.1.2
-c966316c89981bea6ccaa2c2909bb303bfeeb82b release-0.1.6
-d2f04ab4b4127757234af6b30bfc98ad4ee9cb15 release-0.1.4
-d94f1ccac8095509c57ad640d54796aea0d260f0 release-0.1.5
-fe0c1d6f40afa6fca09a277a1ade59231f16c66f release-1.1.1
-5d70fca3be361258edfb59c3edaba5abe75a1e88 release-2.0.0
-df04959950eb3830c39adfa983789f70f86062d7 release-1.1.0
-3396e6dd19fbb52a3fa7e171ffb38ed9acb285a4 release-2.1.1
-ebe0ee3b78101fd526946f55367a69b30195e683 release-3.0.0
-fa8e38bcc3545000a38704b65b604a2c1b764d10 release-3.0.1

+ 105 - 73
physfs.mod/physfs/CMakeLists.txt

@@ -9,27 +9,29 @@
 #  compile, using preprocessor checks for platform-specific bits instead of
 #  testing in here.
 
-cmake_minimum_required(VERSION 2.8.12)
+set(PHYSFS_VERSION 3.3.0)
 
-project(PhysicsFS)
-set(PHYSFS_VERSION 3.1.0)
+cmake_minimum_required(VERSION 3.0)
+
+project(PhysicsFS VERSION ${PHYSFS_VERSION} LANGUAGES C )
+
+include(GNUInstallDirs)
 
 # Increment this if/when we break backwards compatibility.
 set(PHYSFS_SOVERSION 1)
 
-# I hate that they define "WIN32" ... we're about to move to Win64...I hope!
-if(WIN32 AND NOT WINDOWS)
-    set(WINDOWS TRUE)
-endif()
+set(PHYSFS_M_SRCS)
+set(PHYSFS_CPP_SRCS)
 
-include_directories(./src)
+# I hate that they define "WIN32" ... we're about to move to Win64...I hope!
 
 if(APPLE)
     set(OTHER_LDFLAGS ${OTHER_LDFLAGS} "-framework IOKit -framework Foundation")
-    set(PHYSFS_M_SRCS src/physfs_platform_apple.m)
+    list(APPEND PHYSFS_M_SRCS src/physfs_platform_apple.m)
 endif()
 
-if(CMAKE_COMPILER_IS_GNUCC)
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+    add_compile_options(-Wall)
     # Don't use -rpath.
     set(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE)
 endif()
@@ -42,10 +44,10 @@ endif()
 if(HAIKU)
     # We add this explicitly, since we don't want CMake to think this
     #  is a C++ project unless we're on Haiku.
-    set(PHYSFS_CPP_SRCS src/physfs_platform_haiku.cpp)
+    list(APPEND PHYSFS_CPP_SRCS src/physfs_platform_haiku.cpp)
     find_library(BE_LIBRARY be)
     find_library(ROOT_LIBRARY root)
-    set(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${BE_LIBRARY} ${ROOT_LIBRARY})
+    list(APPEND OPTIONAL_LIBRARY_LIBS ${BE_LIBRARY} ${ROOT_LIBRARY})
 endif()
 
 if(CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" OR CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
@@ -53,16 +55,20 @@ if(CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" OR CMAKE_SYSTEM_NAME STREQUAL "Wind
 endif()
 
 if(WINRT)
-    set(PHYSFS_CPP_SRCS src/physfs_platform_winrt.cpp)
+    list(APPEND PHYSFS_CPP_SRCS src/physfs_platform_winrt.cpp)
 endif()
 
-if(UNIX AND NOT WINDOWS AND NOT APPLE)  # (MingW and such might be UNIX _and_ WINDOWS!)
+if(UNIX AND NOT WIN32 AND NOT APPLE)  # (MingW and such might be UNIX _and_ WINDOWS!)
     find_library(PTHREAD_LIBRARY pthread)
     if(PTHREAD_LIBRARY)
         set(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${PTHREAD_LIBRARY})
     endif()
 endif()
 
+if(PHYSFS_CPP_SRCS)
+    enable_language(CXX)
+endif()
+
 # Almost everything is "compiled" here, but things that don't apply to the
 #  build are #ifdef'd out. This is to make it easy to embed PhysicsFS into
 #  another project or bring up a new build system: just compile all the source
@@ -152,6 +158,8 @@ endif()
 option(PHYSFS_BUILD_STATIC "Build static library" TRUE)
 if(PHYSFS_BUILD_STATIC)
     add_library(physfs-static STATIC ${PHYSFS_SRCS})
+    add_library(PhysFS::PhysFS-static ALIAS physfs-static)
+    set_target_properties(physfs-static PROPERTIES EXPORT_NAME PhysFS-static)
     # Don't rename this on Windows, since DLLs will also produce an import
     #  library named "physfs.lib" which would conflict; Unix tend to like the
     #  same library name with a different extension for static libs, but
@@ -164,23 +172,34 @@ if(PHYSFS_BUILD_STATIC)
 		set_target_properties(physfs-static PROPERTIES VS_WINRT_COMPONENT True)
         set_target_properties(physfs-static PROPERTIES STATIC_LIBRARY_FLAGS "/ignore:4264")
     endif()
-
+    if(WIN32 OR WINRT OR OS2)
+        # no dll exports from the static library
+        target_compile_definitions(physfs-static PRIVATE "PHYSFS_STATIC")
+    endif()
+    target_include_directories(physfs-static PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
+    target_link_libraries(physfs-static PRIVATE ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
     set(PHYSFS_LIB_TARGET physfs-static)
-    set(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs-static")
+    list(APPEND PHYSFS_INSTALL_TARGETS "physfs-static")
 endif()
 
 option(PHYSFS_BUILD_SHARED "Build shared library" TRUE)
 if(PHYSFS_BUILD_SHARED)
     add_library(physfs SHARED ${PHYSFS_SRCS})
+    add_library(PhysFS::PhysFS ALIAS physfs)
     set_target_properties(physfs PROPERTIES MACOSX_RPATH 1)
     set_target_properties(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
     set_target_properties(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
+    set_target_properties(physfs PROPERTIES EXPORT_NAME PhysFS)
     if(WINRT)
 		set_target_properties(physfs PROPERTIES VS_WINRT_COMPONENT True)
     endif()
-    target_link_libraries(physfs ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
+    if(OS2) # OS/2 does not support a DLL name longer than 8 characters.
+        set_target_properties(physfs PROPERTIES OUTPUT_NAME "physfs")
+    endif()
+    target_include_directories(physfs PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
+    target_link_libraries(physfs PRIVATE ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
     set(PHYSFS_LIB_TARGET physfs)
-    set(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
+    list(APPEND PHYSFS_INSTALL_TARGETS "physfs")
 endif()
 
 if(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
@@ -188,7 +207,7 @@ if(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
 endif()
 
 # CMake FAQ says I need this...
-if(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC AND NOT WINDOWS)
+if(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC AND NOT WIN32)
     set_target_properties(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
     set_target_properties(physfs-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
 endif()
@@ -200,64 +219,88 @@ if(PHYSFS_BUILD_TEST)
     find_path(HISTORY_H readline/history.h)
     if(READLINE_H AND HISTORY_H)
         find_library(CURSES_LIBRARY NAMES curses ncurses)
-        set(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
-        find_library(READLINE_LIBRARY readline)
-        if(READLINE_LIBRARY)
-            set(HAVE_SYSTEM_READLINE TRUE)
-            set(TEST_PHYSFS_LIBS ${TEST_PHYSFS_LIBS} ${READLINE_LIBRARY} ${CURSES_LIBRARY})
-            include_directories(SYSTEM ${READLINE_H} ${HISTORY_H})
-            add_definitions(-DPHYSFS_HAVE_READLINE=1)
+        if(CURSES_LIBRARY)
+            set(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
+            find_library(READLINE_LIBRARY readline)
+            if(READLINE_LIBRARY)
+                set(HAVE_SYSTEM_READLINE TRUE)
+                list(APPEND TEST_PHYSFS_LIBS ${READLINE_LIBRARY} ${CURSES_LIBRARY})
+                include_directories(SYSTEM ${READLINE_H} ${HISTORY_H})
+                add_definitions(-DPHYSFS_HAVE_READLINE=1)
+            endif()
         endif()
     endif()
     add_executable(test_physfs test/test_physfs.c)
-    target_link_libraries(test_physfs ${PHYSFS_LIB_TARGET} ${TEST_PHYSFS_LIBS} ${OTHER_LDFLAGS})
-    set(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";test_physfs")
+    target_link_libraries(test_physfs PRIVATE ${PHYSFS_LIB_TARGET} ${TEST_PHYSFS_LIBS} ${OTHER_LDFLAGS})
+    list(APPEND PHYSFS_INSTALL_TARGETS test_physfs)
 endif()
 
-install(TARGETS ${PHYSFS_INSTALL_TARGETS} EXPORT PhysFSExport
-        RUNTIME DESTINATION bin
-        LIBRARY DESTINATION lib${LIB_SUFFIX}
-        ARCHIVE DESTINATION lib${LIB_SUFFIX}
-        INCLUDES DESTINATION include)
-install(FILES src/physfs.h DESTINATION include)
-
-install(EXPORT PhysFSExport
-        DESTINATION "lib${LIB_SUFFIX}/cmake/PhysFS"
-        FILE PhysFSConfig.cmake
-)
+option(PHYSFS_DISABLE_INSTALL "Disable installing PhysFS" OFF)
+if(NOT PHYSFS_DISABLE_INSTALL)
 
+    install(TARGETS ${PHYSFS_INSTALL_TARGETS} EXPORT PhysFSExport
+            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+            INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+    install(FILES src/physfs.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
 
-find_package(Doxygen)
-if(DOXYGEN_FOUND)
-    set(PHYSFS_OUTPUT_DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
-    configure_file(
-        "${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile"
-        "${PHYSFS_OUTPUT_DOXYFILE}"
-        COPYONLY
+    install(EXPORT PhysFSExport
+            DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/PhysFS"
+            FILE PhysFSConfig.cmake
+            NAMESPACE PhysFS::
     )
-    file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n\n# Below auto-generated by cmake...\n\n")
-    file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "PROJECT_NUMBER = \"${PHYSFS_VERSION}\"\n")
-    file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "OUTPUT_DIRECTORY = \"${CMAKE_CURRENT_BINARY_DIR}/docs\"\n")
-    file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n# End auto-generated section.\n\n")
 
-    set(PHYSFS_TARGETNAME_DOCS "docs" CACHE STRING "Name of 'docs' build target")
-    add_custom_target(
-        ${PHYSFS_TARGETNAME_DOCS}
-        ${DOXYGEN_EXECUTABLE} "${PHYSFS_OUTPUT_DOXYFILE}"
-        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-        COMMENT "Building documentation in 'docs' directory..."
-    )
-else()
-    message(STATUS "Doxygen not found. You won't be able to build documentation.")
+    if(NOT MSVC)
+        configure_file(
+            "extras/physfs.pc.in"
+            "extras/physfs.pc"
+            @ONLY
+        )
+
+        install(
+            FILES "${CMAKE_CURRENT_BINARY_DIR}/extras/physfs.pc"
+            DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
+        )
+    endif()
+endif()
+
+option(PHYSFS_BUILD_DOCS "Build doxygen based documentation" TRUE)
+if(PHYSFS_BUILD_DOCS)
+    find_package(Doxygen)
+    if(DOXYGEN_FOUND)
+        set(PHYSFS_OUTPUT_DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
+        configure_file(
+            "${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile"
+            "${PHYSFS_OUTPUT_DOXYFILE}"
+            COPYONLY
+        )
+        file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n\n# Below auto-generated by cmake...\n\n")
+        file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "PROJECT_NUMBER = \"${PHYSFS_VERSION}\"\n")
+        file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "OUTPUT_DIRECTORY = \"${CMAKE_CURRENT_BINARY_DIR}/docs\"\n")
+        file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n# End auto-generated section.\n\n")
+
+        set(PHYSFS_TARGETNAME_DOCS "docs" CACHE STRING "Name of 'docs' build target")
+
+        add_custom_target(
+            ${PHYSFS_TARGETNAME_DOCS}
+            ${DOXYGEN_EXECUTABLE} "${PHYSFS_OUTPUT_DOXYFILE}"
+            WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+            COMMENT "Building documentation in 'docs' directory..."
+        )
+
+    else()
+        message(STATUS "Doxygen not found. You won't be able to build documentation.")
+    endif()
 endif()
 
 if(UNIX)
-    set(PHYSFS_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../physfs-${PHYSFS_VERSION}.tar.bz2")
+    set(PHYSFS_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../physfs-${PHYSFS_VERSION}.tar.gz")
 
     set(PHYSFS_TARGETNAME_DIST "dist" CACHE STRING "Name of 'dist' build target")
     add_custom_target(
         ${PHYSFS_TARGETNAME_DIST}
-        hg archive -t tbz2 "${PHYSFS_TARBALL}"
+        git archive --prefix="physfs-${PHYSFS_VERSION}/" --output="${PHYSFS_TARBALL}" HEAD
         WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
         COMMENT "Building source tarball '${PHYSFS_TARBALL}'..."
     )
@@ -271,17 +314,6 @@ if(UNIX)
     )
 endif()
 
-if(NOT MSVC)
-    configure_file(
-        "extras/physfs.pc.in"
-        "extras/physfs.pc"
-        @ONLY
-    )
-    install(
-        FILES "${CMAKE_CURRENT_BINARY_DIR}/extras/physfs.pc"
-        DESTINATION "lib${LIB_SUFFIX}/pkgconfig"
-    )
-endif()
 
 macro(message_bool_option _NAME _VALUE)
     if(${_VALUE})
@@ -305,9 +337,9 @@ message_bool_option("ISO9660 support" PHYSFS_ARCHIVE_ISO9660)
 message_bool_option("Build static library" PHYSFS_BUILD_STATIC)
 message_bool_option("Build shared library" PHYSFS_BUILD_SHARED)
 message_bool_option("Build stdio test program" PHYSFS_BUILD_TEST)
+message_bool_option("Build Doxygen documentation" PHYSFS_BUILD_DOCS)
 if(PHYSFS_BUILD_TEST)
     message_bool_option("  Use readline in test program" HAVE_SYSTEM_READLINE)
 endif()
 
 # end of CMakeLists.txt ...
-

+ 16 - 22
physfs.mod/physfs/LICENSE.txt

@@ -1,23 +1,17 @@
-
-   Copyright (c) 2001-2020 Ryan C. Gordon and others.
-
-   This software is provided 'as-is', without any express or implied warranty.
-   In no event will the authors be held liable for any damages arising from
-   the use of this software.
-
-   Permission is granted to anyone to use this software for any purpose,
-   including commercial applications, and to alter it and redistribute it
-   freely, subject to the following restrictions:
-
-   1. The origin of this software must not be misrepresented; you must not
-   claim that you wrote the original software. If you use this software in a
-   product, an acknowledgment in the product documentation would be
-   appreciated but is not required.
-
-   2. Altered source versions must be plainly marked as such, and must not be
+Copyright (c) 2001-2022 Ryan C. Gordon <[email protected]> and others.
+  
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+  
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software. If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required. 
+2. Altered source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.
-
-   3. This notice may not be removed or altered from any source distribution.
-
-       Ryan C. Gordon <[email protected]>
-
+3. This notice may not be removed or altered from any source distribution.

+ 1 - 1
physfs.mod/physfs/docs/CHANGELOG.txt

@@ -6,6 +6,6 @@ The changelog is no longer maintained by hand. It made sense to have a single
 If you want a list of changes, updated in real time, just point your web
  browser here:
 
-    https://hg.icculus.org/icculus/physfs/
+    https://github.com/icculus/physfs/commits/
 
 

+ 3 - 3
physfs.mod/physfs/extras/buildbot-checker.sh

@@ -1,7 +1,7 @@
 prefix=@CMAKE_INSTALL_PREFIX@
-exec_prefix=${prefix}
-libdir=${exec_prefix}/lib
-includedir=${prefix}/include
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
 
 Name: PhysicsFS
 Description: PhysicsFS is a library to provide abstract access to various archives.

+ 93 - 0
physfs.mod/physfs/extras/uninstall.sh

@@ -0,0 +1,93 @@
+# Open Watcom makefile to build PhysicsFS for OS/2
+# wmake -f Makefile.os2
+
+LIBNAME = physfs
+VERSION = 3.3.0
+
+LIBFILE = $(LIBNAME).lib
+DLLFILE = $(LIBNAME).dll
+LNKFILE = $(LIBNAME).lnk
+
+TITLENAME = $(LIBNAME) $(VERSION)
+
+SRCS = physfs.c                   &
+       physfs_byteorder.c         &
+       physfs_unicode.c           &
+       physfs_platform_os2.c      &
+       physfs_archiver_dir.c      &
+       physfs_archiver_unpacked.c &
+       physfs_archiver_grp.c      &
+       physfs_archiver_hog.c      &
+       physfs_archiver_7z.c       &
+       physfs_archiver_mvl.c      &
+       physfs_archiver_qpak.c     &
+       physfs_archiver_wad.c      &
+       physfs_archiver_zip.c      &
+       physfs_archiver_slb.c      &
+       physfs_archiver_iso9660.c  &
+       physfs_archiver_vdf.c
+
+
+OBJS = $(SRCS:.c=.obj)
+
+CFLAGS_BASE = -bt=os2 -d0 -q -bm -5s -fp5 -fpi87 -sg -oeatxh -ei -j
+CFLAGS_BASE+= -DNDEBUG
+# warnings:
+CFLAGS_BASE+= -wx
+# newer OpenWatcom versions enable W303 by default
+CFLAGS_BASE+= -wcd=303
+# include paths:
+CFLAGS_BASE+= -I"$(%WATCOM)/h/os2" -I"$(%WATCOM)/h"
+CFLAGS = $(CFLAGS_BASE)
+# to build a dll:
+CFLAGS+= -bd
+
+.extensions:
+.extensions: .lib .dll .obj .c
+
+all: $(DLLFILE) test_physfs.exe
+
+.c: decoders
+.c: examples
+
+$(LIBFILE): $(DLLFILE)
+  @echo * Create library: $@...
+  wlib -b -n -q -c -pa -s -t -zld -ii -io $@ $(DLLFILE)
+
+$(DLLFILE): $(OBJS) $(MODPLIB) $(TIMILIB) $(LNKFILE)
+  @echo * Link: $@
+  wlink @$(LNKFILE)
+
+$(LNKFILE):
+  @%create $@
+  @%append $@ SYSTEM os2v2_dll INITINSTANCE TERMINSTANCE
+  @%append $@ NAME $(LIBNAME)
+  @for %i in ($(OBJS)) do @%append $@ FILE %i
+  @%append $@ OPTION QUIET
+  @%append $@ OPTION DESCRIPTION '@$#icculus org:$(VERSION)$#@PhysicsFS'
+  @%append $@ OPTION MAP=$^&.map
+  @%append $@ OPTION ELIMINATE
+  @%append $@ OPTION MANYAUTODATA
+  @%append $@ OPTION OSNAME='OS/2 and eComStation'
+  @%append $@ OPTION SHOWDEAD
+
+.c.obj:
+  wcc386 $(CFLAGS) -fo=$^@ $<
+
+test_physfs.obj: "../test/test_physfs.c"
+  wcc386 $(CFLAGS_BASE) -fo=$^@ $<
+
+test_physfs.exe: $(LIBFILE) test_physfs.obj
+  @echo * Link: $@
+  wlink SYS os2v2 LIBR {$(LIBFILE)} op q op el F {test_physfs.obj} N test_physfs.exe
+
+clean: .SYMBOLIC
+  @echo * Clean: $(TITLENAME)
+  @if exist *.obj rm *.obj
+  @if exist *.err rm *.err
+  @if exist $(LNKFILE) rm $(LNKFILE)
+distclean: .SYMBOLIC clean
+  @if exist $(DLLFILE) rm $(DLLFILE)
+  @if exist $(LIBFILE) rm $(LIBFILE)
+  @if exist *.map rm *.map
+  @if exist *.exe rm *.exe

+ 81 - 26
physfs.mod/physfs/src/physfs.c

@@ -12,8 +12,6 @@
 #include "physfs_internal.h"
 
 #if defined(_MSC_VER)
-#include <stdarg.h>
-
 /* this code came from https://stackoverflow.com/a/8712996 */
 int __PHYSFS_msvc_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
 {
@@ -104,8 +102,8 @@ static inline int __PHYSFS_atomicAdd(int *ptrval, const int val)
 {
     int retval;
     __PHYSFS_platformGrabMutex(stateLock);
+    *ptrval += val;
     retval = *ptrval;
-    *ptrval = retval + val;
     __PHYSFS_platformReleaseMutex(stateLock);
     return retval;
 } /* __PHYSFS_atomicAdd */
@@ -923,12 +921,12 @@ static DirHandle *openDirectory(PHYSFS_Io *io, const char *d, int forWriting)
             retval = tryOpenDir(io, *i, d, forWriting, &claimed);
     } /* else */
 
-    errcode = currentErrorCode();
+    errcode = claimed ? currentErrorCode() : PHYSFS_ERR_UNSUPPORTED;
 
     if ((!retval) && (created_io))
         io->destroy(io);
 
-    BAIL_IF(!retval, claimed ? errcode : PHYSFS_ERR_UNSUPPORTED, NULL);
+    BAIL_IF(!retval, errcode, NULL);
     return retval;
 } /* openDirectory */
 
@@ -1095,6 +1093,8 @@ static int freeDirHandle(DirHandle *dh, FileHandle *openList)
         BAIL_IF(i->dirHandle == dh, PHYSFS_ERR_FILES_STILL_OPEN, 0);
 
     dh->funcs->closeArchive(dh->opaque);
+
+    if (dh->root) allocator.Free(dh->root);
     allocator.Free(dh->dirName);
     allocator.Free(dh->mountPoint);
     allocator.Free(dh);
@@ -1435,15 +1435,60 @@ char *__PHYSFS_strdup(const char *str)
 } /* __PHYSFS_strdup */
 
 
-PHYSFS_uint32 __PHYSFS_hashString(const char *str, size_t len)
+PHYSFS_uint32 __PHYSFS_hashString(const char *str)
 {
     PHYSFS_uint32 hash = 5381;
-    while (len--)
-        hash = ((hash << 5) + hash) ^ *(str++);
+    while (1)
+    {
+        const char ch = *(str++);
+        if (ch == 0)
+            break;
+        hash = ((hash << 5) + hash) ^ ch;
+    } /* while */
     return hash;
 } /* __PHYSFS_hashString */
 
 
+PHYSFS_uint32 __PHYSFS_hashStringCaseFold(const char *str)
+{
+    PHYSFS_uint32 hash = 5381;
+    while (1)
+    {
+        const PHYSFS_uint32 cp = __PHYSFS_utf8codepoint(&str);
+        if (cp == 0)
+            break;
+        else
+        {
+            PHYSFS_uint32 folded[3];
+            const int numbytes = (int) (PHYSFS_caseFold(cp, folded) * sizeof (PHYSFS_uint32));
+            const char *bytes = (const char *) folded;
+            int i;
+            for (i = 0; i < numbytes; i++)
+                hash = ((hash << 5) + hash) ^ *(bytes++);
+        } /* else */
+    } /* while */
+
+    return hash;
+} /* __PHYSFS_hashStringCaseFold */
+
+
+PHYSFS_uint32 __PHYSFS_hashStringCaseFoldUSAscii(const char *str)
+{
+    PHYSFS_uint32 hash = 5381;
+    while (1)
+    {
+        char ch = *(str++);
+        if (ch == 0)
+            break;
+        else if ((ch >= 'A') && (ch <= 'Z'))
+            ch -= ('A' - 'a');
+
+        hash = ((hash << 5) + hash) ^ ch;
+    } /* while */
+    return hash;
+} /* __PHYSFS_hashStringCaseFoldUSAscii */
+
+
 /* MAKE SURE you hold stateLock before calling this! */
 static int doRegisterArchiver(const PHYSFS_Archiver *_archiver)
 {
@@ -1735,10 +1780,10 @@ int PHYSFS_setRoot(const char *archive, const char *subdir)
                 if (i->root)
                     allocator.Free(i->root);
                 i->root = ptr;
-                i->rootlen = len;
+                i->rootlen = strlen(i->root);  /* in case sanitizePlatformIndependentPath changed subdir */
 
-                if (longest_root < len)
-                    longest_root = len;
+                if (longest_root < i->rootlen)
+                    longest_root = i->rootlen;
             } /* else */
 
             break;
@@ -2109,10 +2154,10 @@ static int verifyPath(DirHandle *h, char **_fname, int allowMissing)
     if (h->root)
     {
         const int isempty = (*fname == '\0');
-        fname -= h->rootlen - 1;
+        fname -= h->rootlen + (isempty ? 0 : 1);
         strcpy(fname, h->root);
         if (!isempty)
-            fname[h->rootlen - 2] = '/';
+            fname[h->rootlen] = '/';
         *_fname = fname;
     } /* if */
 
@@ -2189,7 +2234,12 @@ static int doMkdir(const char *_dname, char *dname)
             const int rc = h->funcs->stat(h->opaque, dname, &statbuf);
             if ((!rc) && (currentErrorCode() == PHYSFS_ERR_NOT_FOUND))
                 exists = 0;
-            retval = ((rc) && (statbuf.filetype == PHYSFS_FILETYPE_DIRECTORY));
+            /* verifyPath made sure that (dname) doesn't have symlinks if they aren't
+               allowed, but it's possible the mounted writeDir itself has symlinks in it,
+               (for example "/var" on iOS is a symlink, and the prefpath will be somewhere
+               under that)...if we mounted that writeDir, we must allow those symlinks here
+               unconditionally. */
+            retval = ( (rc) && ((statbuf.filetype == PHYSFS_FILETYPE_DIRECTORY) || (statbuf.filetype == PHYSFS_FILETYPE_SYMLINK)) );
         } /* if */
 
         if (!exists)
@@ -2267,10 +2317,10 @@ static DirHandle *getRealDirHandle(const char *_fname)
     BAIL_IF(!_fname, PHYSFS_ERR_INVALID_ARGUMENT, NULL);
 
     __PHYSFS_platformGrabMutex(stateLock);
-    len = strlen(_fname) + longest_root + 1;
+    len = strlen(_fname) + longest_root + 2;
     allocated_fname = __PHYSFS_smallAlloc(len);
     BAIL_IF_MUTEX(!allocated_fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, NULL);
-    fname = allocated_fname + longest_root;
+    fname = allocated_fname + longest_root + 1;
     if (sanitizePlatformIndependentPath(_fname, fname))
     {
         DirHandle *i;
@@ -2498,10 +2548,10 @@ int PHYSFS_enumerate(const char *_fn, PHYSFS_EnumerateCallback cb, void *data)
 
     __PHYSFS_platformGrabMutex(stateLock);
 
-    len = strlen(_fn) + longest_root + 1;
+    len = strlen(_fn) + longest_root + 2;
     allocated_fname = (char *) __PHYSFS_smallAlloc(len);
     BAIL_IF_MUTEX(!allocated_fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
-    fname = allocated_fname + longest_root;
+    fname = allocated_fname + longest_root + 1;
     if (!sanitizePlatformIndependentPath(_fn, fname))
         retval = PHYSFS_ENUM_STOP;
     else
@@ -2704,10 +2754,10 @@ PHYSFS_File *PHYSFS_openRead(const char *_fname)
 
     BAIL_IF_MUTEX(!searchPath, PHYSFS_ERR_NOT_FOUND, stateLock, 0);
 
-    len = strlen(_fname) + longest_root + 1;
+    len = strlen(_fname) + longest_root + 2;
     allocated_fname = (char *) __PHYSFS_smallAlloc(len);
     BAIL_IF_MUTEX(!allocated_fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
-    fname = allocated_fname + longest_root;
+    fname = allocated_fname + longest_root + 1;
 
     if (sanitizePlatformIndependentPath(_fname, fname))
     {
@@ -3095,10 +3145,10 @@ int PHYSFS_stat(const char *_fname, PHYSFS_Stat *stat)
     stat->readonly = 1;
 
     __PHYSFS_platformGrabMutex(stateLock);
-    len = strlen(_fname) + longest_root + 1;
+    len = strlen(_fname) + longest_root + 2;
     allocated_fname = (char *) __PHYSFS_smallAlloc(len);
     BAIL_IF_MUTEX(!allocated_fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
-    fname = allocated_fname + longest_root;
+    fname = allocated_fname + longest_root + 1;
 
     if (sanitizePlatformIndependentPath(_fname, fname))
     {
@@ -3231,7 +3281,7 @@ static void setDefaultAllocator(void)
 } /* setDefaultAllocator */
 
 
-int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen)
+int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen, const int case_sensitive, const int only_usascii)
 {
     static char rootpath[2] = { '/', '\0' };
     size_t alloclen;
@@ -3239,6 +3289,8 @@ int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen)
     assert(entrylen >= sizeof (__PHYSFS_DirTreeEntry));
 
     memset(dt, '\0', sizeof (*dt));
+    dt->case_sensitive = case_sensitive;
+    dt->only_usascii = only_usascii;
 
     dt->root = (__PHYSFS_DirTreeEntry *) allocator.Malloc(entrylen);
     BAIL_IF(!dt->root, PHYSFS_ERR_OUT_OF_MEMORY, 0);
@@ -3259,9 +3311,10 @@ int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen)
 } /* __PHYSFS_DirTreeInit */
 
 
-static inline PHYSFS_uint32 hashPathName(__PHYSFS_DirTree *dt, const char *name)
+static PHYSFS_uint32 hashPathName(__PHYSFS_DirTree *dt, const char *name)
 {
-    return __PHYSFS_hashString(name, strlen(name)) % dt->hashBuckets;
+    const PHYSFS_uint32 hashval = dt->case_sensitive ? __PHYSFS_hashString(name) : dt->only_usascii ? __PHYSFS_hashStringCaseFoldUSAscii(name) : __PHYSFS_hashStringCaseFold(name);
+    return hashval % dt->hashBuckets;
 } /* hashPathName */
 
 
@@ -3322,6 +3375,7 @@ void *__PHYSFS_DirTreeAdd(__PHYSFS_DirTree *dt, char *name, const int isdir)
 /* Find the __PHYSFS_DirTreeEntry for a path in platform-independent notation. */
 void *__PHYSFS_DirTreeFind(__PHYSFS_DirTree *dt, const char *path)
 {
+    const int cs = dt->case_sensitive;
     PHYSFS_uint32 hashval;
     __PHYSFS_DirTreeEntry *prev = NULL;
     __PHYSFS_DirTreeEntry *retval;
@@ -3332,7 +3386,8 @@ void *__PHYSFS_DirTreeFind(__PHYSFS_DirTree *dt, const char *path)
     hashval = hashPathName(dt, path);
     for (retval = dt->hash[hashval]; retval; retval = retval->hashnext)
     {
-        if (strcmp(retval->name, path) == 0)
+        const int cmp = cs ? strcmp(retval->name, path) : PHYSFS_utf8stricmp(retval->name, path);
+        if (cmp == 0)
         {
             if (prev != NULL)  /* move this to the front of the list */
             {

+ 4 - 2
physfs.mod/physfs/src/physfs.h

@@ -225,7 +225,9 @@ extern "C" {
 
 #if defined(PHYSFS_DECL)
 /* do nothing. */
-#elif defined(_MSC_VER)
+#elif defined(PHYSFS_STATIC)
+#define PHYSFS_DECL   /**/
+#elif defined(_WIN32) || defined(__OS2__)
 #define PHYSFS_DECL __declspec(dllexport)
 #elif defined(__SUNPRO_C)
 #define PHYSFS_DECL __global
@@ -433,7 +435,7 @@ typedef struct PHYSFS_Version
 
 #ifndef DOXYGEN_SHOULD_IGNORE_THIS
 #define PHYSFS_VER_MAJOR 3
-#define PHYSFS_VER_MINOR 1
+#define PHYSFS_VER_MINOR 3
 #define PHYSFS_VER_PATCH 0
 #endif  /* DOXYGEN_SHOULD_IGNORE_THIS */
 

+ 1 - 1
physfs.mod/physfs/src/physfs_archiver_7z.c

@@ -185,7 +185,7 @@ static int szipLoadEntries(SZIPinfo *info)
 {
     int retval = 0;
 
-    if (__PHYSFS_DirTreeInit(&info->tree, sizeof (SZIPentry)))
+    if (__PHYSFS_DirTreeInit(&info->tree, sizeof (SZIPentry), 1, 0))
     {
         const PHYSFS_uint32 count = info->db.NumFiles;
         PHYSFS_uint32 i;

+ 1 - 1
physfs.mod/physfs/src/physfs_archiver_grp.c

@@ -76,7 +76,7 @@ static void *GRP_openArchive(PHYSFS_Io *io, const char *name,
     BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof(count)), NULL);
     count = PHYSFS_swapULE32(count);
 
-    unpkarc = UNPK_openArchive(io);
+    unpkarc = UNPK_openArchive(io, 0, 1);
     BAIL_IF_ERRPASS(!unpkarc, NULL);
 
     if (!grpLoadEntries(io, count, unpkarc))

+ 1 - 1
physfs.mod/physfs/src/physfs_archiver_hog.c

@@ -130,7 +130,7 @@ static void *HOG_openArchive(PHYSFS_Io *io, const char *name,
 
     *claimed = 1;
 
-    unpkarc = UNPK_openArchive(io);
+    unpkarc = UNPK_openArchive(io, 0, 1);
     BAIL_IF_ERRPASS(!unpkarc, NULL);
 
     if (!(hog1 ? hog1LoadEntries(io, unpkarc) : hog2LoadEntries(io, unpkarc)))

+ 3 - 2
physfs.mod/physfs/src/physfs_archiver_iso9660.c

@@ -251,7 +251,7 @@ static int parseVolumeDescriptor(PHYSFS_Io *io, PHYSFS_uint64 *_rootpos,
         pos += 2048;  /* each volume descriptor is 2048 bytes */
 
         BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &type, 1), 0);
-        BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &identifier, 5), 0);
+        BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, identifier, 5), 0);
 
         if (memcmp(identifier, "CD001", 5) != 0)  /* maybe not an iso? */
         {
@@ -346,7 +346,8 @@ static void *ISO9660_openArchive(PHYSFS_Io *io, const char *filename,
     if (!parseVolumeDescriptor(io, &rootpos, &len, &joliet, claimed))
         return NULL;
 
-    unpkarc = UNPK_openArchive(io);
+    /* !!! FIXME: check case_sensitive and only_usascii params for this archive. */
+    unpkarc = UNPK_openArchive(io, 1, 0);
     BAIL_IF_ERRPASS(!unpkarc, NULL);
 
     if (!iso9660LoadEntries(io, joliet, "", rootpos, rootpos + len, unpkarc))

+ 1 - 1
physfs.mod/physfs/src/physfs_archiver_mvl.c

@@ -70,7 +70,7 @@ static void *MVL_openArchive(PHYSFS_Io *io, const char *name,
     BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof(count)), NULL);
     count = PHYSFS_swapULE32(count);
 
-    unpkarc = UNPK_openArchive(io);
+    unpkarc = UNPK_openArchive(io, 0, 1);
     BAIL_IF_ERRPASS(!unpkarc, NULL);
 
     if (!mvlLoadEntries(io, count, unpkarc))

+ 2 - 1
physfs.mod/physfs/src/physfs_archiver_qpak.c

@@ -86,7 +86,8 @@ static void *QPAK_openArchive(PHYSFS_Io *io, const char *name,
 
     BAIL_IF_ERRPASS(!io->seek(io, pos), NULL);
 
-    unpkarc = UNPK_openArchive(io);
+    /* !!! FIXME: check case_sensitive and only_usascii params for this archive. */
+    unpkarc = UNPK_openArchive(io, 1, 0);
     BAIL_IF_ERRPASS(!unpkarc, NULL);
 
     if (!qpakLoadEntries(io, count, unpkarc))

+ 3 - 2
physfs.mod/physfs/src/physfs_archiver_slb.c

@@ -36,7 +36,7 @@ static int slbLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count, void *arc)
         BAIL_IF(backslash != '\\', PHYSFS_ERR_CORRUPT, 0);
 
         /* read the rest of the buffer, 63 bytes */
-        BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &name, 63), 0);
+        BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 63), 0);
         name[63] = '\0'; /* in case the name lacks the null terminator */
 
         /* convert backslashes */
@@ -94,7 +94,8 @@ static void *SLB_openArchive(PHYSFS_Io *io, const char *name,
     /* seek to the table of contents */
     BAIL_IF_ERRPASS(!io->seek(io, tocPos), NULL);
 
-    unpkarc = UNPK_openArchive(io);
+    /* !!! FIXME: check case_sensitive and only_usascii params for this archive. */
+    unpkarc = UNPK_openArchive(io, 1, 0);
     BAIL_IF_ERRPASS(!unpkarc, NULL);
 
     if (!slbLoadEntries(io, count, unpkarc))

+ 2 - 2
physfs.mod/physfs/src/physfs_archiver_unpacked.c

@@ -285,12 +285,12 @@ void *UNPK_addEntry(void *opaque, char *name, const int isdir,
 } /* UNPK_addEntry */
 
 
-void *UNPK_openArchive(PHYSFS_Io *io)
+void *UNPK_openArchive(PHYSFS_Io *io, const int case_sensitive, const int only_usascii)
 {
     UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
     BAIL_IF(!info, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
 
-    if (!__PHYSFS_DirTreeInit(&info->tree, sizeof (UNPKentry)))
+    if (!__PHYSFS_DirTreeInit(&info->tree, sizeof (UNPKentry), case_sensitive, only_usascii))
     {
         allocator.Free(info);
         return NULL;

+ 2 - 1
physfs.mod/physfs/src/physfs_archiver_vdf.c

@@ -129,7 +129,8 @@ static void *VDF_openArchive(PHYSFS_Io *io, const char *name,
 
     BAIL_IF_ERRPASS(!io->seek(io, rootCatOffset), NULL);
 
-    unpkarc = UNPK_openArchive(io);
+    /* !!! FIXME: check case_sensitive and only_usascii params for this archive. */
+    unpkarc = UNPK_openArchive(io, 1, 0);
     BAIL_IF_ERRPASS(!unpkarc, NULL);
 
     if (!vdfLoadEntries(io, count, vdfDosTimeToEpoch(timestamp), unpkarc))

+ 1 - 1
physfs.mod/physfs/src/physfs_archiver_wad.c

@@ -95,7 +95,7 @@ static void *WAD_openArchive(PHYSFS_Io *io, const char *name,
 
     BAIL_IF_ERRPASS(!io->seek(io, directoryOffset), 0);
 
-    unpkarc = UNPK_openArchive(io);
+    unpkarc = UNPK_openArchive(io, 0, 1);
     BAIL_IF_ERRPASS(!unpkarc, NULL);
 
     if (!wadLoadEntries(io, count, unpkarc))

+ 12 - 4
physfs.mod/physfs/src/physfs_archiver_zip.c

@@ -15,6 +15,11 @@
 #include <errno.h>
 #include <time.h>
 
+#if (PHYSFS_BYTEORDER == PHYSFS_LIL_ENDIAN)
+#define MINIZ_LITTLE_ENDIAN 1
+#else
+#define MINIZ_LITTLE_ENDIAN 0
+#endif
 #include "physfs_miniz.h"
 
 /*
@@ -568,7 +573,7 @@ static PHYSFS_sint64 zip_find_end_of_central_dir(PHYSFS_Io *io, PHYSFS_sint64 *l
         {
             if (!__PHYSFS_readAll(io, buf, maxread - 4))
                 return -1;
-            memcpy(&buf[maxread - 4], &extra, sizeof (extra));
+            memcpy(&buf[maxread - 4], extra, sizeof (extra));
             totalread += maxread - 4;
         } /* if */
         else
@@ -578,7 +583,7 @@ static PHYSFS_sint64 zip_find_end_of_central_dir(PHYSFS_Io *io, PHYSFS_sint64 *l
             totalread += maxread;
         } /* else */
 
-        memcpy(&extra, buf, sizeof (extra));
+        memcpy(extra, buf, sizeof (extra));
 
         for (i = maxread - 4; i > 0; i--)
         {
@@ -833,7 +838,10 @@ static int zip_parse_local(PHYSFS_Io *io, ZIPentry *entry)
     BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
     BAIL_IF(ui32 != ZIP_LOCAL_FILE_SIG, PHYSFS_ERR_CORRUPT, 0);
     BAIL_IF_ERRPASS(!readui16(io, &ui16), 0);
-    BAIL_IF(ui16 != entry->version_needed, PHYSFS_ERR_CORRUPT, 0);
+    /* Windows Explorer might rewrite the entire central directory, setting
+       this field to 2.0/MS-DOS for all files, so favor the local version,
+       which it leaves intact if it didn't alter that specific file. */
+    entry->version_needed = ui16;
     BAIL_IF_ERRPASS(!readui16(io, &ui16), 0);  /* general bits. */
     BAIL_IF_ERRPASS(!readui16(io, &ui16), 0);
     BAIL_IF(ui16 != entry->compression_method, PHYSFS_ERR_CORRUPT, 0);
@@ -1482,7 +1490,7 @@ static void *ZIP_openArchive(PHYSFS_Io *io, const char *name,
 
     if (!zip_parse_end_of_central_dir(info, &dstart, &cdir_ofs, &count))
         goto ZIP_openarchive_failed;
-    else if (!__PHYSFS_DirTreeInit(&info->tree, sizeof (ZIPentry)))
+    else if (!__PHYSFS_DirTreeInit(&info->tree, sizeof (ZIPentry), 1, 0))
         goto ZIP_openarchive_failed;
 
     root = (ZIPentry *) info->tree.root;

+ 57 - 10
physfs.mod/physfs/src/physfs_internal.h

@@ -38,7 +38,7 @@
 #include <malloc.h>
 #endif
 
-#ifdef PHYSFS_PLATFORM_SOLARIS
+#if defined(PHYSFS_PLATFORM_SOLARIS) || defined(PHYSFS_PLATFORM_LINUX)
 #include <alloca.h>
 #endif
 
@@ -69,7 +69,7 @@ extern "C" {
    All file-private symbols need to be marked "static".
    Everything shared between PhysicsFS sources needs to be in this
    file between the visibility pragma blocks. */
-#if PHYSFS_MINIMUM_GCC_VERSION(4,0) || defined(__clang__)
+#if !defined(_WIN32) && (PHYSFS_MINIMUM_GCC_VERSION(4,0) || defined(__clang__))
 #define PHYSFS_HAVE_PRAGMA_VISIBILITY 1
 #endif
 
@@ -95,6 +95,7 @@ extern const PHYSFS_Archiver __PHYSFS_Archiver_VDF;
 /* a real C99-compliant snprintf() is in Visual Studio 2015,
    but just use this everywhere for binary compatibility. */
 #if defined(_MSC_VER)
+#include <stdarg.h>
 int __PHYSFS_msvc_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap);
 int __PHYSFS_msvc_snprintf(char *outBuf, size_t size, const char *format, ...);
 #define vsnprintf __PHYSFS_msvc_vsnprintf
@@ -108,14 +109,24 @@ const void *__PHYSFS_winrtCalcPrefDir(void);
 #endif
 
 /* atomic operations. */
+/* increment/decrement operations return the final incremented/decremented value. */
 #if defined(_MSC_VER) && (_MSC_VER >= 1500)
 #include <intrin.h>
 __PHYSFS_COMPILE_TIME_ASSERT(LongEqualsInt, sizeof (int) == sizeof (long));
 #define __PHYSFS_ATOMIC_INCR(ptrval) _InterlockedIncrement((long*)(ptrval))
 #define __PHYSFS_ATOMIC_DECR(ptrval) _InterlockedDecrement((long*)(ptrval))
 #elif defined(__clang__) || (defined(__GNUC__) && (((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100)) >= 40100))
-#define __PHYSFS_ATOMIC_INCR(ptrval) __sync_fetch_and_add(ptrval, 1)
-#define __PHYSFS_ATOMIC_DECR(ptrval) __sync_fetch_and_add(ptrval, -1)
+#define __PHYSFS_ATOMIC_INCR(ptrval) __sync_add_and_fetch(ptrval, 1)
+#define __PHYSFS_ATOMIC_DECR(ptrval) __sync_add_and_fetch(ptrval, -1)
+#elif defined(__WATCOMC__) && defined(__386__)
+extern __inline int _xadd_watcom(volatile int *a, int v);
+#pragma aux _xadd_watcom = \
+  "lock xadd [ecx], eax" \
+  parm [ecx] [eax] \
+  value [eax] \
+  modify exact [eax];
+#define __PHYSFS_ATOMIC_INCR(ptrval) (_xadd_watcom(ptrval, 1)+1)
+#define __PHYSFS_ATOMIC_DECR(ptrval) (_xadd_watcom(ptrval, -1)-1)
 #else
 #define PHYSFS_NEED_ATOMIC_OP_FALLBACK 1
 int __PHYSFS_ATOMIC_INCR(int *ptrval);
@@ -213,6 +224,7 @@ extern void SZIP_global_init(void);
 /* The latest supported PHYSFS_Archiver::version value. */
 #define CURRENT_PHYSFS_ARCHIVER_API_VERSION 0
 
+
 /* This byteorder stuff was lifted from SDL. https://www.libsdl.org/ */
 #define PHYSFS_LIL_ENDIAN  1234
 #define PHYSFS_BIG_ENDIAN  4321
@@ -220,11 +232,26 @@ extern void SZIP_global_init(void);
 #ifdef __linux__
 #include <endian.h>
 #define PHYSFS_BYTEORDER  __BYTE_ORDER
-#else /* __linux__ */
+#elif defined(__OpenBSD__) || defined(__DragonFly__)
+#include <endian.h>
+#define PHYSFS_BYTEORDER  BYTE_ORDER
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+#include <sys/endian.h>
+#define PHYSFS_BYTEORDER  BYTE_ORDER
+/* predefs from newer gcc and clang versions: */
+#elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__)
+#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define PHYSFS_BYTEORDER   PHYSFS_LIL_ENDIAN
+#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define PHYSFS_BYTEORDER   PHYSFS_BIG_ENDIAN
+#else
+#error Unsupported endianness
+#endif /**/
+#else
 #if defined(__hppa__) || \
     defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
-    (defined(__MIPS__) && defined(__MISPEB__)) || \
-    defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
+    (defined(__MIPS__) && defined(__MIPSEB__)) || \
+    defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(__PPC__) || \
     defined(__sparc__)
 #define PHYSFS_BYTEORDER   PHYSFS_BIG_ENDIAN
 #else
@@ -312,7 +339,18 @@ char *__PHYSFS_strdup(const char *str);
 /*
  * Give a hash value for a C string (uses djb's xor hashing algorithm).
  */
-PHYSFS_uint32 __PHYSFS_hashString(const char *str, size_t len);
+PHYSFS_uint32 __PHYSFS_hashString(const char *str);
+
+/*
+ * Give a hash value for a C string (uses djb's xor hashing algorithm), case folding as it goes.
+ */
+PHYSFS_uint32 __PHYSFS_hashStringCaseFold(const char *str);
+
+/*
+ * Give a hash value for a C string (uses djb's xor hashing algorithm), case folding as it goes,
+ *  assuming that this is only US-ASCII chars (one byte per char, only 'A' through 'Z' need folding).
+ */
+PHYSFS_uint32 __PHYSFS_hashStringCaseFoldUSAscii(const char *str);
 
 
 /*
@@ -348,9 +386,10 @@ int __PHYSFS_readAll(PHYSFS_Io *io, void *buf, const size_t len);
 
 /* These are shared between some archivers. */
 
+/* LOTS of legacy formats that only use US ASCII, not actually UTF-8, so let them optimize here. */
+void *UNPK_openArchive(PHYSFS_Io *io, const int case_sensitive, const int only_usascii);
 void UNPK_abandonArchive(void *opaque);
 void UNPK_closeArchive(void *opaque);
-void *UNPK_openArchive(PHYSFS_Io *io);
 void *UNPK_addEntry(void *opaque, char *name, const int isdir,
                     const PHYSFS_sint64 ctime, const PHYSFS_sint64 mtime,
                     const PHYSFS_uint64 pos, const PHYSFS_uint64 len);
@@ -382,10 +421,13 @@ typedef struct __PHYSFS_DirTree
     __PHYSFS_DirTreeEntry **hash;  /* all entries hashed for fast lookup. */
     size_t hashBuckets;            /* number of buckets in hash.          */
     size_t entrylen;    /* size in bytes of entries (including subclass). */
+    int case_sensitive;  /* non-zero to treat entries as case-sensitive in DirTreeFind */
+    int only_usascii;  /* non-zero to treat paths as US ASCII only (one byte per char, only 'A' through 'Z' are considered for case folding). */
 } __PHYSFS_DirTree;
 
 
-int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen);
+/* LOTS of legacy formats that only use US ASCII, not actually UTF-8, so let them optimize here. */
+int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen, const int case_sensitive, const int only_usascii);
 void *__PHYSFS_DirTreeAdd(__PHYSFS_DirTree *dt, char *name, const int isdir);
 void *__PHYSFS_DirTreeFind(__PHYSFS_DirTree *dt, const char *path);
 PHYSFS_EnumerateCallbackResult __PHYSFS_DirTreeEnumerate(void *opaque,
@@ -715,6 +757,11 @@ int __PHYSFS_platformGrabMutex(void *mutex);
  */
 void __PHYSFS_platformReleaseMutex(void *mutex);
 
+
+/* !!! FIXME: move to public API? */
+PHYSFS_uint32 __PHYSFS_utf8codepoint(const char **_str);
+
+
 #if PHYSFS_HAVE_PRAGMA_VISIBILITY
 #pragma GCC visibility pop
 #endif

+ 3 - 0
physfs.mod/physfs/src/physfs_lzmasdk.h

@@ -506,6 +506,7 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
 #endif
 
 #if defined(MY_CPU_AMD64) \
+    || defined(_M_ARM64) \
     || defined(_M_IA64) \
     || defined(__AARCH64EL__) \
     || defined(__AARCH64EB__)
@@ -531,6 +532,8 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
 
 #if defined(_WIN32) && defined(_M_ARM)
 #define MY_CPU_ARM_LE
+#elif defined(_WIN64) && defined(_M_ARM64)
+#define MY_CPU_ARM_LE
 #endif
 
 #if defined(_WIN32) && defined(_M_IA64)

+ 13 - 5
physfs.mod/physfs/src/physfs_miniz.h

@@ -22,12 +22,14 @@ typedef unsigned long mz_ulong;
 typedef void *(*mz_alloc_func)(void *opaque, unsigned int items, unsigned int size);
 typedef void (*mz_free_func)(void *opaque, void *address);
 
+#ifndef MINIZ_LITTLE_ENDIAN /* if not defined by PHYSFS */
 #if defined(_M_IX86) || defined(_M_X64)
 /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 if integer loads and stores to unaligned addresses are acceptable on the target platform (slightly faster). */
 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
 /* Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. */
 #define MINIZ_LITTLE_ENDIAN 1
 #endif
+#endif /**/
 
 #if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__)
 /* Set MINIZ_HAS_64BIT_REGISTERS to 1 if the processor has 64-bit general purpose registers (enables 64-bit bitbuffer in inflator) */
@@ -117,6 +119,8 @@ struct tinfl_decompressor_tag
 #define MZ_MAX(a,b) (((a)>(b))?(a):(b))
 #define MZ_MIN(a,b) (((a)<(b))?(a):(b))
 #define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
+#define MZ_CLEAR_ARR(obj) memset((obj), 0, sizeof(obj))
+#define MZ_CLEAR_PTR(obj) memset((obj), 0, sizeof(*obj))
 
 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
   #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
@@ -166,13 +170,17 @@ struct tinfl_decompressor_tag
     if (temp >= 0) { \
       code_len = temp >> 9; \
       if ((code_len) && (num_bits >= code_len)) \
-      break; \
+          break; \
     } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
        code_len = TINFL_FAST_LOOKUP_BITS; \
        do { \
           temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
-       } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
-    } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
+       } while ((temp < 0) && (num_bits >= (code_len + 1))); \
+       if (temp >= 0) break; \
+    } \
+    TINFL_GET_BYTE(state_index, c); \
+    bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
+    num_bits += 8; \
   } while (num_bits < 15);
 
 /* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */
@@ -274,13 +282,13 @@ static tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_
       else
       {
         for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
-        MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
+        MZ_CLEAR_ARR(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
         r->m_table_sizes[2] = 19;
       }
       for ( ; (int)r->m_type >= 0; r->m_type--)
       {
         int tree_next, tree_cur; tinfl_huff_table *pTable;
-        mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
+        mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_ARR(total_syms); MZ_CLEAR_ARR(pTable->m_look_up); MZ_CLEAR_ARR(pTable->m_tree);
         for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
         used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
         for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }

+ 19 - 6
physfs.mod/physfs/src/physfs_platform_apple.m

@@ -12,6 +12,7 @@
 #ifdef PHYSFS_PLATFORM_APPLE
 
 #include <Foundation/Foundation.h>
+#include <dlfcn.h>
 
 #include "physfs_internal.h"
 
@@ -99,7 +100,7 @@ static int darwinIsWholeMedia(io_service_t service)
 } /* darwinIsWholeMedia */
 
 
-static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
+static int darwinIsMountedDisc(char *bsdName, mach_port_t mainPort)
 {
     int retval = 0;
     CFMutableDictionaryRef matchingDict;
@@ -107,10 +108,10 @@ static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
     io_iterator_t iter;
     io_service_t service;
 
-    if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL)
+    if ((matchingDict = IOBSDNameMatching(mainPort, 0, bsdName)) == NULL)
         return 0;
 
-    rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter);
+    rc = IOServiceGetMatchingServices(mainPort, matchingDict, &iter);
     if ((rc != KERN_SUCCESS) || (!iter))
         return 0;
 
@@ -158,13 +159,25 @@ static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
 void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
 {
 #if !defined(PHYSFS_NO_CDROM_SUPPORT)
+    /* macOS 12.0 changed "master" names to "main". */
+    typedef kern_return_t (*ioMainPortFn)(mach_port_t, mach_port_t *);
+    static ioMainPortFn ioMainPort = NULL;
     const char *devPrefix = "/dev/";
     const int prefixLen = strlen(devPrefix);
-    mach_port_t masterPort = 0;
+    mach_port_t mainPort = 0;
     struct statfs *mntbufp;
     int i, mounts;
 
-    if (IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS)
+    if (ioMainPort == NULL)
+    {
+        ioMainPort = (ioMainPortFn) dlsym(RTLD_DEFAULT, "IOMainPort");
+        if (!ioMainPort)
+            ioMainPort = (ioMainPortFn) dlsym(RTLD_DEFAULT, "IOMasterPort");
+        if (!ioMainPort)
+            return; /* oh well, no CD-ROMs for you. */
+    } /* if */
+
+    if (ioMainPort(MACH_PORT_NULL, &mainPort) != KERN_SUCCESS)
         BAIL(PHYSFS_ERR_OS_ERROR, ) /*return void*/;
 
     mounts = getmntinfo(&mntbufp, MNT_WAIT);  /* NOT THREAD SAFE! */
@@ -176,7 +189,7 @@ void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
             continue;
 
         dev += prefixLen;
-        if (darwinIsMountedDisc(dev, masterPort))
+        if (darwinIsMountedDisc(dev, mainPort))
             cb(data, mnt);
     } /* for */
 #endif /* !defined(PHYSFS_NO_CDROM_SUPPORT) */

+ 4 - 4
physfs.mod/physfs/src/physfs_platform_os2.c

@@ -222,7 +222,7 @@ static char *cvtPathToCorrectCase(char *buf)
         if (ptr != NULL)  /* isolate element to find (fname is the start). */
             *ptr = '\0';
 
-        rc = DosFindFirst((unsigned char *) spec, &hdir, FILE_DIRECTORY,
+        rc = DosFindFirst(spec, &hdir, FILE_DIRECTORY,
                           &fb, sizeof (fb), &count, FIL_STANDARD);
         if (rc == NO_ERROR)
         {
@@ -331,7 +331,7 @@ static int isCdRomDrive(ULONG drive)
     ULONG ul1, ul2;
     APIRET rc;
     HFILE hfile = NULLHANDLE;
-    unsigned char drivename[3] = { 0, ':', '\0' };
+    char drivename[3] = { 0, ':', '\0' };
 
     drivename[0] = 'A' + drive;
 
@@ -443,7 +443,7 @@ PHYSFS_EnumerateCallbackResult __PHYSFS_platformEnumerate(const char *dirname,
     __PHYSFS_smallFree(utf8);
     BAIL_IF_ERRPASS(!cpspec, PHYSFS_ENUM_ERROR);
 
-    rc = DosFindFirst((unsigned char *) cpspec, &hdir,
+    rc = DosFindFirst(cpspec, &hdir,
                       FILE_DIRECTORY | FILE_ARCHIVED |
                       FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM,
                       &fb, sizeof (fb), &count, FIL_STANDARD);
@@ -535,7 +535,7 @@ int __PHYSFS_platformMkDir(const char *filename)
     APIRET rc;
     char *cpstr = cvtUtf8ToCodepage(filename);
     BAIL_IF_ERRPASS(!cpstr, 0);
-    rc = DosCreateDir((unsigned char *) cpstr, NULL);
+    rc = DosCreateDir(cpstr, NULL);
     allocator.Free(cpstr);
     BAIL_IF(rc != NO_ERROR, errcodeFromAPIRET(rc), 0);
     return 1;

+ 40 - 8
physfs.mod/physfs/src/physfs_platform_posix.c

@@ -6,8 +6,6 @@
  *  This file written by Ryan C. Gordon.
  */
 
-/* !!! FIXME: check for EINTR? */
-
 #define __PHYSICSFS_INTERNAL__
 #include "physfs_platforms.h"
 
@@ -157,19 +155,41 @@ int __PHYSFS_platformMkDir(const char *path)
 } /* __PHYSFS_platformMkDir */
 
 
+#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC)
+static inline void set_CLOEXEC(int fildes)
+{
+    int flags = fcntl(fildes, F_GETFD);
+    if (flags != -1) {
+        fcntl(fildes, F_SETFD, flags | FD_CLOEXEC);
+    }
+}
+#endif
+
 static void *doOpen(const char *filename, int mode)
 {
     const int appending = (mode & O_APPEND);
     int fd;
     int *retval;
+
     errno = 0;
 
     /* O_APPEND doesn't actually behave as we'd like. */
     mode &= ~O_APPEND;
 
-    fd = open(filename, mode, S_IRUSR | S_IWUSR);
+#ifdef O_CLOEXEC
+    /* Add O_CLOEXEC if defined */
+    mode |= O_CLOEXEC;
+#endif
+
+    do {
+        fd = open(filename, mode, S_IRUSR | S_IWUSR);
+    } while ((fd < 0) && (errno == EINTR));
     BAIL_IF(fd < 0, errcodeFromErrno(), NULL);
 
+#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC)
+    set_CLOEXEC(fd);
+#endif
+
     if (appending)
     {
         if (lseek(fd, 0, SEEK_END) < 0)
@@ -219,7 +239,9 @@ PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
     if (!__PHYSFS_ui64FitsAddressSpace(len))
         BAIL(PHYSFS_ERR_INVALID_ARGUMENT, -1);
 
-    rc = read(fd, buffer, (size_t) len);
+    do {
+        rc = read(fd, buffer, (size_t) len);
+    } while ((rc == -1) && (errno == EINTR));
     BAIL_IF(rc == -1, errcodeFromErrno(), -1);
     assert(rc >= 0);
     assert(rc <= len);
@@ -236,7 +258,9 @@ PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
     if (!__PHYSFS_ui64FitsAddressSpace(len))
         BAIL(PHYSFS_ERR_INVALID_ARGUMENT, -1);
 
-    rc = write(fd, (void *) buffer, (size_t) len);
+    do {
+        rc = write(fd, (void *) buffer, (size_t) len);
+    } while ((rc == -1) && (errno == EINTR));
     BAIL_IF(rc == -1, errcodeFromErrno(), rc);
     assert(rc >= 0);
     assert(rc <= len);
@@ -275,8 +299,13 @@ PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
 int __PHYSFS_platformFlush(void *opaque)
 {
     const int fd = *((int *) opaque);
-    if ((fcntl(fd, F_GETFL) & O_ACCMODE) != O_RDONLY)
-        BAIL_IF(fsync(fd) == -1, errcodeFromErrno(), 0);
+    int rc = -1;
+    if ((fcntl(fd, F_GETFL) & O_ACCMODE) != O_RDONLY) {
+        do {
+            rc = fsync(fd);
+        } while ((rc == -1) && (errno == EINTR));
+        BAIL_IF(rc == -1, errcodeFromErrno(), 0);
+    }
     return 1;
 } /* __PHYSFS_platformFlush */
 
@@ -284,7 +313,10 @@ int __PHYSFS_platformFlush(void *opaque)
 void __PHYSFS_platformClose(void *opaque)
 {
     const int fd = *((int *) opaque);
-    (void) close(fd);  /* we don't check this. You should have used flush! */
+    int rc = -1;
+    do {
+        rc = close(fd);  /* we don't check this. You should have used flush! */
+    } while ((rc == -1) && (errno == EINTR));
     allocator.Free(opaque);
 } /* __PHYSFS_platformClose */
 

+ 5 - 5
physfs.mod/physfs/src/physfs_platform_windows.c

@@ -101,7 +101,7 @@ static char *unicodeToUtf8Heap(const WCHAR *w_str)
 
 static inline HANDLE winFindFirstFileW(const WCHAR *path, LPWIN32_FIND_DATAW d)
 {
-    #ifdef PHYSFS_PLATFORM_WINRT
+    #if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0501) // Windows XP+
     return FindFirstFileExW(path, FindExInfoStandard, d,
                             FindExSearchNameMatch, NULL, 0);
     #else
@@ -111,7 +111,7 @@ static inline HANDLE winFindFirstFileW(const WCHAR *path, LPWIN32_FIND_DATAW d)
 
 static inline BOOL winInitializeCriticalSection(LPCRITICAL_SECTION lpcs)
 {
-    #ifdef PHYSFS_PLATFORM_WINRT
+    #if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0600) // Windows Vista+
     return InitializeCriticalSectionEx(lpcs, 2000, 0);
     #else
     InitializeCriticalSection(lpcs);
@@ -123,7 +123,7 @@ static inline HANDLE winCreateFileW(const WCHAR *wfname, const DWORD mode,
                                     const DWORD creation)
 {
     const DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
-    #ifdef PHYSFS_PLATFORM_WINRT
+    #if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0602) // Windows 8+
     return CreateFile2(wfname, mode, share, creation, NULL);
     #else
     return CreateFileW(wfname, mode, share, NULL, creation,
@@ -134,7 +134,7 @@ static inline HANDLE winCreateFileW(const WCHAR *wfname, const DWORD mode,
 static BOOL winSetFilePointer(HANDLE h, const PHYSFS_sint64 pos,
                               PHYSFS_sint64 *_newpos, const DWORD whence)
 {
-    #ifdef PHYSFS_PLATFORM_WINRT
+    #if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0501) // Windows XP+
     LARGE_INTEGER lipos;
     LARGE_INTEGER linewpos;
     BOOL rc;
@@ -158,7 +158,7 @@ static BOOL winSetFilePointer(HANDLE h, const PHYSFS_sint64 pos,
 
 static PHYSFS_sint64 winGetFileSize(HANDLE h)
 {
-    #ifdef PHYSFS_PLATFORM_WINRT
+    #if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0600) // Windows Vista+
     FILE_STANDARD_INFO info;
     const BOOL rc = GetFileInformationByHandleEx(h, FileStandardInfo,
                                                  &info, sizeof (info));

+ 12 - 7
physfs.mod/physfs/src/physfs_unicode.c

@@ -21,8 +21,8 @@
 /*
  * This may not be the best value, but it's one that isn't represented
  *  in Unicode (0x10FFFF is the largest codepoint value). We return this
- *  value from utf8codepoint() if there's bogus bits in the
- *  stream. utf8codepoint() will turn this value into something
+ *  value from __PHYSFS_utf8codepoint() if there's bogus bits in the
+ *  stream. __PHYSFS_utf8codepoint() will turn this value into something
  *  reasonable (like a question mark), for text that wants to try to recover,
  *  whereas utf8valid() will use the value to determine if a string has bad
  *  bits.
@@ -35,7 +35,7 @@
  */
 #define UNICODE_BOGUS_CHAR_CODEPOINT '?'
 
-static PHYSFS_uint32 utf8codepoint(const char **_str)
+PHYSFS_uint32 __PHYSFS_utf8codepoint(const char **_str)
 {
     const char *str = *_str;
     PHYSFS_uint32 retval = 0;
@@ -188,6 +188,11 @@ static PHYSFS_uint32 utf8codepoint(const char **_str)
     } /* else if */
 
     return UNICODE_BOGUS_CHAR_VALUE;
+} /* __PHYSFS_utf8codepoint */
+
+static inline PHYSFS_uint32 utf8codepoint(const char **_str)
+{
+    return __PHYSFS_utf8codepoint(_str);
 } /* utf8codepoint */
 
 static PHYSFS_uint32 utf16codepoint(const PHYSFS_uint16 **_str)
@@ -210,7 +215,7 @@ static PHYSFS_uint32 utf16codepoint(const PHYSFS_uint16 **_str)
         else
         {
             src++;  /* eat the other surrogate. */
-            cp = (((cp - 0xD800) << 10) | (pair - 0xDC00));
+            cp = 0x10000 + (((cp - 0xD800) << 10) | (pair - 0xDC00));
         } /* else */
     } /* else if */
 
@@ -238,7 +243,7 @@ void PHYSFS_utf8ToUcs4(const char *src, PHYSFS_uint32 *dst, PHYSFS_uint64 len)
     len -= sizeof (PHYSFS_uint32);   /* save room for null char. */
     while (len >= sizeof (PHYSFS_uint32))
     {
-        PHYSFS_uint32 cp = utf8codepoint(&src);
+        PHYSFS_uint32 cp = __PHYSFS_utf8codepoint(&src);
         if (cp == 0)
             break;
         else if (cp == UNICODE_BOGUS_CHAR_VALUE)
@@ -256,7 +261,7 @@ void PHYSFS_utf8ToUcs2(const char *src, PHYSFS_uint16 *dst, PHYSFS_uint64 len)
     len -= sizeof (PHYSFS_uint16);   /* save room for null char. */
     while (len >= sizeof (PHYSFS_uint16))
     {
-        PHYSFS_uint32 cp = utf8codepoint(&src);
+        PHYSFS_uint32 cp = __PHYSFS_utf8codepoint(&src);
         if (cp == 0)
             break;
         else if (cp == UNICODE_BOGUS_CHAR_VALUE)
@@ -278,7 +283,7 @@ void PHYSFS_utf8ToUtf16(const char *src, PHYSFS_uint16 *dst, PHYSFS_uint64 len)
     len -= sizeof (PHYSFS_uint16);   /* save room for null char. */
     while (len >= sizeof (PHYSFS_uint16))
     {
-        PHYSFS_uint32 cp = utf8codepoint(&src);
+        PHYSFS_uint32 cp = __PHYSFS_utf8codepoint(&src);
         if (cp == 0)
             break;
         else if (cp == UNICODE_BOGUS_CHAR_VALUE)

+ 1 - 1
physfs.mod/physfs/test/test_physfs.c

@@ -31,7 +31,7 @@
 #include "physfs.h"
 
 #define TEST_VERSION_MAJOR  3
-#define TEST_VERSION_MINOR  1
+#define TEST_VERSION_MINOR  3
 #define TEST_VERSION_PATCH  0
 
 static FILE *history_file = NULL;