Added PhysFS lib
This commit is contained in:
5
project/jni/physfs/.hg_archival.txt
Normal file
5
project/jni/physfs/.hg_archival.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
repo: 7672c9962ce627edaaa67ff54fe4ad8f9a46dc2b
|
||||
node: 92a35b8603186c536e4cc126458dfc2d2809b19c
|
||||
branch: stable-2.0
|
||||
latesttag: release-2.0.2
|
||||
latesttagdistance: 1
|
||||
2
project/jni/physfs/.hgignore
Normal file
2
project/jni/physfs/.hgignore
Normal file
@@ -0,0 +1,2 @@
|
||||
syntax:glob
|
||||
cmake-build
|
||||
16
project/jni/physfs/.hgtags
Normal file
16
project/jni/physfs/.hgtags
Normal file
@@ -0,0 +1,16 @@
|
||||
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
|
||||
94771621792f838aa4cacf9a1e1f4f86c1cb0711 release-2.0.1
|
||||
236afd18dd8cae34adb9897024bdcecc1dc8ca5d release-2.0.2
|
||||
24
project/jni/physfs/Android.mk
Normal file
24
project/jni/physfs/Android.mk
Normal file
@@ -0,0 +1,24 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := physfs
|
||||
|
||||
APP_SUBDIRS := . archivers platform include
|
||||
|
||||
LOCAL_CFLAGS := -O2 -fsigned-char -Dphysfs_EXPORTS -D_REENTRANT -D_THREAD_SAFE -DHAVE_ASSERT_H=1 -DPHYSFS_SUPPORTS_ZIP=1 -DPHYSFS_SUPPORTS_GRP=1 -DPHYSFS_SUPPORTS_HOG=1 -DPHYSFS_SUPPORTS_MVL=1 -DPHYSFS_SUPPORTS_QPAK=1 -D_FILE_OFFSET_BITS=32 -D_LARGE_FILES -DPHYSFS_NO_CDROM_SUPPORT=1
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cpp
|
||||
|
||||
LOCAL_C_INCLUDES := $(foreach F, $(APP_SUBDIRS), $(LOCAL_PATH)/$(F))
|
||||
|
||||
LOCAL_SRC_FILES := $(foreach F, $(APP_SUBDIRS), $(addprefix $(F)/,$(notdir $(wildcard $(LOCAL_PATH)/$(F)/*.c))))
|
||||
|
||||
LOCAL_STATIC_LIBRARIES :=
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := lzma
|
||||
|
||||
LOCAL_LDLIBS := -lz
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
11
project/jni/physfs/CHANGELOG.txt
Normal file
11
project/jni/physfs/CHANGELOG.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
The changelog is no longer maintained by hand. It made sense to have a single
|
||||
timeline when we were using CVS, but modern revision control tools make this
|
||||
redundant, at best.
|
||||
|
||||
If you want a list of changes, updated in real time, just point your web
|
||||
browser here:
|
||||
|
||||
http://hg.icculus.org/icculus/physfs/
|
||||
|
||||
|
||||
388
project/jni/physfs/CMakeLists.txt
Normal file
388
project/jni/physfs/CMakeLists.txt
Normal file
@@ -0,0 +1,388 @@
|
||||
# PhysicsFS; a portable, flexible file i/o abstraction.
|
||||
# Copyright (C) 2007 Ryan C. Gordon.
|
||||
#
|
||||
# Please see the file LICENSE.txt in the source's root directory.
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
|
||||
|
||||
PROJECT(PhysicsFS)
|
||||
SET(PHYSFS_VERSION 2.0.2)
|
||||
|
||||
# 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(WIN32 AND NOT WINDOWS)
|
||||
|
||||
# Bleh, let's do it for "APPLE" too.
|
||||
IF(APPLE AND NOT MACOSX)
|
||||
SET(MACOSX TRUE)
|
||||
ENDIF(APPLE AND NOT MACOSX)
|
||||
|
||||
INCLUDE(CheckIncludeFile)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
|
||||
INCLUDE_DIRECTORIES(.)
|
||||
#INCLUDE_DIRECTORIES(platform)
|
||||
#INCLUDE_DIRECTORIES(archivers)
|
||||
|
||||
IF(MACOSX)
|
||||
# Fallback to older OS X on PowerPC to support wider range of systems...
|
||||
IF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
|
||||
ADD_DEFINITIONS(-DMAC_OS_X_VERSION_MIN_REQUIRED=1020)
|
||||
SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -mmacosx-version-min=10.2")
|
||||
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
|
||||
|
||||
# Need these everywhere...
|
||||
ADD_DEFINITIONS(-fno-common)
|
||||
SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -framework Carbon -framework IOKit")
|
||||
ENDIF(MACOSX)
|
||||
|
||||
# Add some gcc-specific command lines.
|
||||
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||
# Always build with debug symbols...you can strip it later.
|
||||
ADD_DEFINITIONS(-g -pipe -Werror -fsigned-char)
|
||||
|
||||
# Stupid BeOS generates warnings in the system headers.
|
||||
IF(NOT BEOS)
|
||||
ADD_DEFINITIONS(-Wall)
|
||||
ENDIF(NOT BEOS)
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
#if ((defined(__GNUC__)) && (__GNUC__ >= 4))
|
||||
int main(int argc, char **argv) { int is_gcc4 = 1; return 0; }
|
||||
#else
|
||||
#error This is not gcc4.
|
||||
#endif
|
||||
" PHYSFS_IS_GCC4)
|
||||
|
||||
IF(PHYSFS_IS_GCC4)
|
||||
# Not supported on several operating systems at this time.
|
||||
IF(NOT OS2 AND NOT SOLARIS AND NOT WINDOWS)
|
||||
ADD_DEFINITIONS(-fvisibility=hidden)
|
||||
ENDIF(NOT OS2 AND NOT SOLARIS AND NOT WINDOWS)
|
||||
ENDIF(PHYSFS_IS_GCC4)
|
||||
ENDIF(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
IF(MSVC)
|
||||
# VS.NET 8.0 got really really anal about strcpy, etc, which even if we
|
||||
# cleaned up our code, zlib, etc still use...so disable the warning.
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1)
|
||||
ENDIF(MSVC)
|
||||
|
||||
# Basic chunks of source code ...
|
||||
|
||||
SET(ZLIB_SRCS
|
||||
zlib123/adler32.c
|
||||
zlib123/compress.c
|
||||
zlib123/crc32.c
|
||||
zlib123/deflate.c
|
||||
zlib123/gzio.c
|
||||
zlib123/infback.c
|
||||
zlib123/inffast.c
|
||||
zlib123/inflate.c
|
||||
zlib123/inftrees.c
|
||||
zlib123/trees.c
|
||||
zlib123/uncompr.c
|
||||
zlib123/zutil.c
|
||||
)
|
||||
|
||||
SET(LZMA_SRCS
|
||||
lzma/C/7zCrc.c
|
||||
lzma/C/Archive/7z/7zBuffer.c
|
||||
lzma/C/Archive/7z/7zDecode.c
|
||||
lzma/C/Archive/7z/7zExtract.c
|
||||
lzma/C/Archive/7z/7zHeader.c
|
||||
lzma/C/Archive/7z/7zIn.c
|
||||
lzma/C/Archive/7z/7zItem.c
|
||||
lzma/C/Archive/7z/7zMethodID.c
|
||||
lzma/C/Compress/Branch/BranchX86.c
|
||||
lzma/C/Compress/Branch/BranchX86_2.c
|
||||
lzma/C/Compress/Lzma/LzmaDecode.c
|
||||
)
|
||||
|
||||
IF(BEOS)
|
||||
# We add this explicitly, since we don't want CMake to think this
|
||||
# is a C++ project unless we're on BeOS.
|
||||
SET(PHYSFS_BEOS_SRCS platform/beos.cpp)
|
||||
FIND_LIBRARY(BE_LIBRARY be)
|
||||
FIND_LIBRARY(ROOT_LIBRARY root)
|
||||
SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${BE_LIBRARY} ${ROOT_LIBRARY})
|
||||
ENDIF(BEOS)
|
||||
|
||||
# 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
|
||||
# code and #define the things you want.
|
||||
SET(PHYSFS_SRCS
|
||||
physfs.c
|
||||
physfs_byteorder.c
|
||||
physfs_unicode.c
|
||||
platform/os2.c
|
||||
platform/pocketpc.c
|
||||
platform/posix.c
|
||||
platform/unix.c
|
||||
platform/macosx.c
|
||||
platform/windows.c
|
||||
archivers/dir.c
|
||||
archivers/grp.c
|
||||
archivers/hog.c
|
||||
archivers/lzma.c
|
||||
archivers/mvl.c
|
||||
archivers/qpak.c
|
||||
archivers/wad.c
|
||||
archivers/zip.c
|
||||
${PHYSFS_BEOS_SRCS}
|
||||
)
|
||||
|
||||
|
||||
# platform layers ...
|
||||
|
||||
IF(UNIX)
|
||||
IF(BEOS)
|
||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
||||
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
|
||||
SET(HAVE_PTHREAD_H TRUE)
|
||||
ELSE(BEOS)
|
||||
# !!! FIXME
|
||||
# AC_DEFINE([PHYSFS_HAVE_LLSEEK], 1, [define if we have llseek])
|
||||
CHECK_INCLUDE_FILE(sys/ucred.h HAVE_UCRED_H)
|
||||
IF(HAVE_UCRED_H)
|
||||
ADD_DEFINITIONS(-DPHYSFS_HAVE_SYS_UCRED_H=1)
|
||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
||||
ENDIF(HAVE_UCRED_H)
|
||||
|
||||
CHECK_INCLUDE_FILE(mntent.h HAVE_MNTENT_H)
|
||||
IF(HAVE_MNTENT_H)
|
||||
ADD_DEFINITIONS(-DPHYSFS_HAVE_MNTENT_H=1)
|
||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
||||
ENDIF(HAVE_MNTENT_H)
|
||||
|
||||
CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
|
||||
IF(HAVE_PTHREAD_H)
|
||||
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
|
||||
ENDIF(HAVE_PTHREAD_H)
|
||||
ENDIF(BEOS)
|
||||
ENDIF(UNIX)
|
||||
|
||||
IF(WINDOWS)
|
||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
||||
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
|
||||
ENDIF(WINDOWS)
|
||||
|
||||
IF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
|
||||
ADD_DEFINITIONS(-DPHYSFS_NO_CDROM_SUPPORT=1)
|
||||
MESSAGE(WARNING " ***")
|
||||
MESSAGE(WARNING " *** There is no CD-ROM support in this build!")
|
||||
MESSAGE(WARNING " *** PhysicsFS will just pretend there are no discs.")
|
||||
MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
|
||||
MESSAGE(WARNING " *** but is this what you REALLY wanted?")
|
||||
MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
|
||||
MESSAGE(WARNING " ***")
|
||||
ENDIF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
|
||||
|
||||
IF(PHYSFS_HAVE_THREAD_SUPPORT)
|
||||
ADD_DEFINITIONS(-D_REENTRANT -D_THREAD_SAFE)
|
||||
ELSE(PHYSFS_HAVE_THREAD_SUPPORT)
|
||||
ADD_DEFINITIONS(-DPHYSFS_NO_THREAD_SUPPORT=1)
|
||||
MESSAGE(WARNING " ***")
|
||||
MESSAGE(WARNING " *** There is no thread support in this build!")
|
||||
MESSAGE(WARNING " *** PhysicsFS will NOT be reentrant!")
|
||||
MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
|
||||
MESSAGE(WARNING " *** but is this what you REALLY wanted?")
|
||||
MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
|
||||
MESSAGE(WARNING " ***")
|
||||
ENDIF(PHYSFS_HAVE_THREAD_SUPPORT)
|
||||
|
||||
CHECK_INCLUDE_FILE(assert.h HAVE_ASSERT_H)
|
||||
IF(HAVE_ASSERT_H)
|
||||
ADD_DEFINITIONS(-DHAVE_ASSERT_H=1)
|
||||
ENDIF(HAVE_ASSERT_H)
|
||||
|
||||
|
||||
|
||||
# Archivers ...
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_ZIP)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_ZIP=1)
|
||||
SET(PHYSFS_NEED_ZLIB TRUE)
|
||||
ENDIF(PHYSFS_ARCHIVE_ZIP)
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_7Z "Enable 7zip support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_7Z)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_7Z=1)
|
||||
# !!! FIXME: rename to 7z.c?
|
||||
SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${LZMA_SRCS})
|
||||
ENDIF(PHYSFS_ARCHIVE_7Z)
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_GRP "Enable Build Engine GRP support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_GRP)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_GRP=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_GRP)
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_WAD "Enable Doom WAD support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_WAD)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_WAD=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_WAD)
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_HOG)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_HOG=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_HOG)
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_MVL "Enable Descent I/II MVL support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_MVL)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_MVL=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_MVL)
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_QPAK "Enable Quake I/II QPAK support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_QPAK)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_QPAK=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_QPAK)
|
||||
|
||||
|
||||
# See if some archiver required zlib, and see about using system version.
|
||||
|
||||
IF(PHYSFS_NEED_ZLIB)
|
||||
FIND_PACKAGE(ZLIB)
|
||||
|
||||
IF(ZLIB_FOUND)
|
||||
OPTION(PHYSFS_INTERNAL_ZLIB "Link own zlib instead of system library" FALSE)
|
||||
ELSE(HAVE_SYSTEM_ZLIB)
|
||||
SET(PHYSFS_INTERNAL_ZLIB TRUE)
|
||||
ENDIF(ZLIB_FOUND)
|
||||
|
||||
IF(PHYSFS_INTERNAL_ZLIB)
|
||||
INCLUDE_DIRECTORIES(zlib123)
|
||||
ADD_DEFINITIONS(-DZ_PREFIX=1)
|
||||
SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${ZLIB_SRCS})
|
||||
ELSE(PHYSFS_INTERNAL_ZLIB)
|
||||
SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${ZLIB_LIBRARY})
|
||||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
|
||||
ENDIF(PHYSFS_INTERNAL_ZLIB)
|
||||
ENDIF(PHYSFS_NEED_ZLIB)
|
||||
|
||||
OPTION(PHYSFS_BUILD_STATIC "Build static library" TRUE)
|
||||
IF(PHYSFS_BUILD_STATIC)
|
||||
ADD_LIBRARY(physfs-static STATIC ${PHYSFS_SRCS})
|
||||
SET_TARGET_PROPERTIES(physfs-static PROPERTIES OUTPUT_NAME "physfs")
|
||||
SET(PHYSFS_LIB_TARGET physfs-static)
|
||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs-static")
|
||||
ENDIF(PHYSFS_BUILD_STATIC)
|
||||
|
||||
OPTION(PHYSFS_BUILD_SHARED "Build shared library" TRUE)
|
||||
IF(PHYSFS_BUILD_SHARED)
|
||||
ADD_LIBRARY(physfs SHARED ${PHYSFS_SRCS})
|
||||
SET_TARGET_PROPERTIES(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
|
||||
SET_TARGET_PROPERTIES(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
|
||||
TARGET_LINK_LIBRARIES(physfs ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
|
||||
SET(PHYSFS_LIB_TARGET physfs)
|
||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
|
||||
ENDIF(PHYSFS_BUILD_SHARED)
|
||||
|
||||
IF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
|
||||
MESSAGE(FATAL "Both shared and static libraries are disabled!")
|
||||
ENDIF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
|
||||
|
||||
# CMake FAQ says I need this...
|
||||
IF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
|
||||
SET_TARGET_PROPERTIES(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
SET_TARGET_PROPERTIES(physfs-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
ENDIF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
|
||||
|
||||
OPTION(PHYSFS_BUILD_TEST "Build stdio test program." TRUE)
|
||||
MARK_AS_ADVANCED(PHYSFS_BUILD_TEST)
|
||||
IF(PHYSFS_BUILD_TEST)
|
||||
FIND_PATH(READLINE_H readline/readline.h)
|
||||
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)
|
||||
FIND_LIBRARY(HISTORY_LIBRARY history)
|
||||
IF(READLINE_LIBRARY AND HISTORY_LIBRARY)
|
||||
SET(HAVE_SYSTEM_READLINE TRUE)
|
||||
SET(TEST_PHYSFS_LIBS ${TEST_PHYSFS_LIBS} ${READLINE_LIBRARY} ${CURSES_LIBRARY})
|
||||
INCLUDE_DIRECTORIES(${READLINE_H} ${HISTORY_H})
|
||||
ADD_DEFINITIONS(-DPHYSFS_HAVE_READLINE=1)
|
||||
ENDIF(READLINE_LIBRARY AND HISTORY_LIBRARY)
|
||||
ENDIF(READLINE_H AND HISTORY_H)
|
||||
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")
|
||||
ENDIF(PHYSFS_BUILD_TEST)
|
||||
|
||||
OPTION(PHYSFS_BUILD_WX_TEST "Build wxWidgets test program." TRUE)
|
||||
MARK_AS_ADVANCED(PHYSFS_BUILD_WX_TEST)
|
||||
IF(PHYSFS_BUILD_WX_TEST)
|
||||
SET(wxWidgets_USE_LIBS base core adv)
|
||||
SET(wxWidgets_INCLUDE_DIRS_NO_SYSTEM 1)
|
||||
FIND_PACKAGE(wxWidgets)
|
||||
IF(wxWidgets_FOUND)
|
||||
INCLUDE(${wxWidgets_USE_FILE})
|
||||
ADD_EXECUTABLE(wxtest_physfs test/wxtest_physfs.cpp)
|
||||
SET_SOURCE_FILES_PROPERTIES(test/wxtest_physfs.cpp COMPILE_FLAGS ${wxWidgets_CXX_FLAGS})
|
||||
TARGET_LINK_LIBRARIES(wxtest_physfs ${PHYSFS_LIB_TARGET} ${wxWidgets_LIBRARIES} ${OTHER_LDFLAGS})
|
||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";wxtest_physfs")
|
||||
ELSE(wxWidgets_FOUND)
|
||||
MESSAGE(STATUS "wxWidgets not found. Disabling wx test app.")
|
||||
SET(PHYSFS_BUILD_WX_TEST FALSE)
|
||||
ENDIF(wxWidgets_FOUND)
|
||||
ENDIF(PHYSFS_BUILD_WX_TEST)
|
||||
|
||||
INSTALL(TARGETS ${PHYSFS_INSTALL_TARGETS}
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(FILES physfs.h DESTINATION include)
|
||||
|
||||
FIND_PACKAGE(Doxygen)
|
||||
IF(DOXYGEN_FOUND)
|
||||
ADD_CUSTOM_TARGET(docs ${DOXYGEN_EXECUTABLE} COMMENT "Building documentation")
|
||||
ELSE(DOXYGEN_FOUND)
|
||||
MESSAGE(STATUS "Doxygen not found. You won't be able to build documentation.")
|
||||
ENDIF(DOXYGEN_FOUND)
|
||||
|
||||
IF(UNIX)
|
||||
SET(PHYSFS_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../physfs-${PHYSFS_VERSION}.tar.gz")
|
||||
ADD_CUSTOM_TARGET(
|
||||
dist
|
||||
hg archive -t tgz "${PHYSFS_TARBALL}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Building source tarball '${PHYSFS_TARBALL}'..."
|
||||
)
|
||||
ENDIF(UNIX)
|
||||
|
||||
MACRO(MESSAGE_BOOL_OPTION _NAME _VALUE)
|
||||
IF(${_VALUE})
|
||||
MESSAGE(STATUS " ${_NAME}: enabled")
|
||||
ELSE(${_VALUE})
|
||||
MESSAGE(STATUS " ${_NAME}: disabled")
|
||||
ENDIF(${_VALUE})
|
||||
ENDMACRO(MESSAGE_BOOL_OPTION)
|
||||
|
||||
MESSAGE(STATUS "PhysicsFS will build with the following options:")
|
||||
MESSAGE_BOOL_OPTION("ZIP support" PHYSFS_ARCHIVE_ZIP)
|
||||
MESSAGE_BOOL_OPTION("7zip support" PHYSFS_ARCHIVE_7Z)
|
||||
MESSAGE_BOOL_OPTION("GRP support" PHYSFS_ARCHIVE_GRP)
|
||||
MESSAGE_BOOL_OPTION("WAD support" PHYSFS_ARCHIVE_WAD)
|
||||
MESSAGE_BOOL_OPTION("HOG support" PHYSFS_ARCHIVE_HOG)
|
||||
MESSAGE_BOOL_OPTION("MVL support" PHYSFS_ARCHIVE_MVL)
|
||||
MESSAGE_BOOL_OPTION("QPAK support" PHYSFS_ARCHIVE_QPAK)
|
||||
MESSAGE_BOOL_OPTION("CD-ROM drive support" PHYSFS_HAVE_CDROM_SUPPORT)
|
||||
MESSAGE_BOOL_OPTION("Thread safety" PHYSFS_HAVE_THREAD_SUPPORT)
|
||||
MESSAGE_BOOL_OPTION("Build own zlib" PHYSFS_INTERNAL_ZLIB)
|
||||
MESSAGE_BOOL_OPTION("Build static library" PHYSFS_BUILD_STATIC)
|
||||
MESSAGE_BOOL_OPTION("Build shared library" PHYSFS_BUILD_SHARED)
|
||||
MESSAGE_BOOL_OPTION("Build wxWidgets test program" PHYSFS_BUILD_WX_TEST)
|
||||
MESSAGE_BOOL_OPTION("Build stdio test program" PHYSFS_BUILD_TEST)
|
||||
IF(PHYSFS_BUILD_TEST)
|
||||
MESSAGE_BOOL_OPTION(" Use readline in test program" HAVE_SYSTEM_READLINE)
|
||||
ENDIF(PHYSFS_BUILD_TEST)
|
||||
|
||||
# end of CMakeLists.txt ...
|
||||
|
||||
113
project/jni/physfs/CREDITS.txt
Normal file
113
project/jni/physfs/CREDITS.txt
Normal file
@@ -0,0 +1,113 @@
|
||||
Maintainer and general codemonkey:
|
||||
Ryan C. Gordon
|
||||
|
||||
Tons of win32 help:
|
||||
Adam Gates
|
||||
|
||||
More win32 hacking:
|
||||
Gregory S. Read
|
||||
|
||||
Fixes for missing current working directories,
|
||||
PHYSFS_setSaneConfig() improvements,
|
||||
other bugfixes:
|
||||
David Hedbor
|
||||
|
||||
Darwin support:
|
||||
Patrick Stein
|
||||
|
||||
configure fixes,
|
||||
RPM specfile:
|
||||
Edward Rudd
|
||||
|
||||
GetLastModTime API,
|
||||
other stuff:
|
||||
John R. Hall
|
||||
|
||||
Various support, fixes and suggestions:
|
||||
Alexander Pipelka
|
||||
|
||||
Russian translation,
|
||||
Ruby bindings,
|
||||
QPAK archiver:
|
||||
Ed Sinjiashvili
|
||||
|
||||
French translation:
|
||||
Stéphane Peter
|
||||
|
||||
Debian package support:
|
||||
Colin Bayer
|
||||
|
||||
"abs-file.h" in "extras" dir:
|
||||
Adam D. Moss
|
||||
|
||||
WinCE port and other Win32 patches:
|
||||
Corona688
|
||||
|
||||
German translation:
|
||||
Michael Renner
|
||||
|
||||
Apple Project Builder support,
|
||||
Mac OS X improvements:
|
||||
Eric Wing
|
||||
|
||||
iPhone support:
|
||||
Christian Gmeiner
|
||||
|
||||
HOG archiver,
|
||||
MVL archiver:
|
||||
Bradley Bell
|
||||
|
||||
MIX archiver:
|
||||
Sebastian Steinhauer
|
||||
|
||||
Bug fixes:
|
||||
Tolga Dalman
|
||||
|
||||
Initial PHYSFS_mount() work:
|
||||
Philip D. Bober
|
||||
|
||||
Brazillian Portuguese translation:
|
||||
Danny Angelo Carminati Grein
|
||||
|
||||
Spanish translation:
|
||||
Pedro J. Pérez
|
||||
|
||||
MacOS Classic fixes,
|
||||
MPW support,
|
||||
bug fixes:
|
||||
Chris Taylor
|
||||
|
||||
Mingw support,
|
||||
General bug fixes:
|
||||
Matze Braun
|
||||
|
||||
Haiku support:
|
||||
scott mc
|
||||
|
||||
Bug fixes:
|
||||
Jörg Walter
|
||||
|
||||
Bug fixes:
|
||||
Olivier Boudeville
|
||||
|
||||
Bug fixes:
|
||||
Henk Boom
|
||||
|
||||
Build system fixes:
|
||||
Marc Kleine-Budde
|
||||
|
||||
Windows .rc file,
|
||||
7zip/lzma archiver:
|
||||
Dennis Schridde
|
||||
|
||||
OS/2 updates:
|
||||
Dave Yeo
|
||||
|
||||
Bug fixes:
|
||||
Patrice Mandin
|
||||
|
||||
Other stuff:
|
||||
Your name here! Patches go to icculus@icculus.org ...
|
||||
|
||||
/* end of CREDITS.txt ... */
|
||||
|
||||
1079
project/jni/physfs/Doxyfile
Normal file
1079
project/jni/physfs/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
153
project/jni/physfs/INSTALL.txt
Normal file
153
project/jni/physfs/INSTALL.txt
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
The latest PhysicsFS information and releases can be found at:
|
||||
http://icculus.org/physfs/
|
||||
|
||||
Building is (ahem) very easy.
|
||||
|
||||
|
||||
ALL PLATFORMS:
|
||||
|
||||
Please understand your rights and mine: read the text file LICENSE.txt in the
|
||||
root of the source tree. If you can't abide by it, delete this source tree
|
||||
now. The license is extremely liberal, even to closed-source, commercial
|
||||
applications.
|
||||
|
||||
If you've got Doxygen (http://www.doxygen.org/) installed, you can run it
|
||||
without any command line arguments in the root of the source tree to generate
|
||||
the API reference (or build the "docs" target from your build system). This
|
||||
is optional. You can browse the API docs online here:
|
||||
|
||||
http://icculus.org/physfs/docs/
|
||||
|
||||
|
||||
|
||||
|
||||
UNIX:
|
||||
|
||||
You will need CMake (http://www.cmake.org/) 2.4 or later installed.
|
||||
|
||||
Make a directory, wherever you like. This will be your build directory.
|
||||
|
||||
Chdir to your build directory. Run "cmake /where/i/unpacked/physfs" to
|
||||
generate Makefiles. You can then run "ccmake ." and customize the build,
|
||||
but the defaults are probably okay. You can have CMake generate KDevelop
|
||||
project files if you prefer these.
|
||||
|
||||
Run "make". PhysicsFS will now build.
|
||||
|
||||
As root, run "make install".
|
||||
If you get sick of the library, run "xargs rm < install_manifest.txt" as root
|
||||
and it will remove all traces of the library from the system paths.
|
||||
|
||||
Once you are satisfied, you can delete the build directory.
|
||||
|
||||
Primary Unix development is done with GNU/Linux, but PhysicsFS is known to
|
||||
work out of the box with several flavors of Unix. It it doesn't work, patches
|
||||
to get it running can be sent to icculus@icculus.org.
|
||||
|
||||
|
||||
|
||||
BeOS, Zeta, and Haiku:
|
||||
|
||||
Use the "Unix" instructions, above. The CMake port to BeOS is fairly new at
|
||||
the time of this writing, but it works. You can get a build of CMake from
|
||||
bebits.com or build it yourself from source from cmake.org.
|
||||
|
||||
|
||||
|
||||
Windows:
|
||||
|
||||
If building with Cygwin, mingw32, MSYS, or something else that uses the GNU
|
||||
toolchain, follow the Unix instructions, above.
|
||||
|
||||
If you want to use Visual Studio, nmake, or the Platform SDK, you will need
|
||||
CMake (http://www.cmake.org/) 2.4 or later installed. Point CMake at the
|
||||
CMakeLists.txt file in the root of the source directory and hit the
|
||||
"Configure" button. After telling it what type of compiler you are targeting
|
||||
(Borland, Visual Studio, etc), CMake will process for while and then give you
|
||||
a list of options you can change (what archivers you want to support, etc).
|
||||
If you aren't sure, the defaults are probably fine. Hit the "Configure"
|
||||
button again, then "OK" once configuration has completed with options that
|
||||
match your liking. Now project files for your favorite programming
|
||||
environment will be generated for you in the directory you specified.
|
||||
Go there and use them to build PhysicsFS.
|
||||
|
||||
PhysicsFS will only link directly against system libraries that have existed
|
||||
since Windows 95 and Windows NT 3.51. If there's a newer API we want to use,
|
||||
we try to dynamically load it at runtime and fallback to a reasonable
|
||||
behaviour when we can't find it...this is used for Unicode support and
|
||||
locating user-specific directories, etc.
|
||||
|
||||
PhysicsFS has not been tested on 64-bit Windows, but probably works. There is
|
||||
no 16-bit Windows support at all. Reports of success and problems can go to
|
||||
Ryan at icculus@icculus.org ...
|
||||
|
||||
If someone is willing to maintain prebuilt PhysicsFS DLLs, I'd like to hear
|
||||
from you; send an email to icculus@icculus.org ...
|
||||
|
||||
|
||||
|
||||
PocketPC/WindowsCE:
|
||||
|
||||
Code exists for PocketPC support, and there are shipping titles that used
|
||||
PhysicsFS 1.0 on PocketPC...but it isn't tested in 2.0, and is probably
|
||||
broken with the new build system. Please send patches.
|
||||
|
||||
|
||||
|
||||
MAC OS 8/9:
|
||||
|
||||
Classic Mac OS support has been dropped in PhysicsFS 2.0. Apple hasn't updated
|
||||
pre-OSX versions in more than a decade at this point, none of the hardware
|
||||
they've shipped will boot it for almost as many years, and finding
|
||||
developer tools for it is becoming almost impossible. As the switch to Intel
|
||||
hardware has removed the "Classic" emulation environment, it was time to
|
||||
remove support from PhysicsFS. That being said, the PhysicsFS 1.0 branch can
|
||||
still target back to Mac OS 8.5, so you can use that if you need support for
|
||||
this legacy OS. We still very much support Mac OS X, though: see below.
|
||||
|
||||
|
||||
|
||||
MAC OS X:
|
||||
|
||||
You will need CMake (http://www.cmake.org/) 2.4 or later installed.
|
||||
|
||||
You can either generate a Unix makefile with CMake, or generate an Xcode
|
||||
project, whichever makes you more comfortable.
|
||||
|
||||
PowerPC and Intel Macs should both be supported.
|
||||
|
||||
If someone is willing to maintain prebuilt PhysicsFS Shared Libraries for
|
||||
Mac OS X, I'd like to hear from you; send an email to icculus@icculus.org.
|
||||
|
||||
|
||||
|
||||
OS/2:
|
||||
|
||||
You need Innotek GCC and libc installed (or kLIBC). I tried this on a stock
|
||||
Warp 4 install, no fixpaks. You need to install link386.exe (Selective
|
||||
Install, "link object modules" option). Once klibc and GCC are installed
|
||||
correctly, unpack the source to PhysicsFS and run the script
|
||||
file "makeos2.cmd". I know this isn't ideal, but I wanted to have this build
|
||||
without users having to hunt down a "make" program.
|
||||
|
||||
Someone please port CMake to OS/2. Ideally I'd like to be able to target
|
||||
Innotek GCC and OpenWatcom with CMake.
|
||||
|
||||
If someone is willing to maintain prebuilt PhysicsFS Shared Libraries for
|
||||
OS/2, I'd like to hear from you; send an email to icculus@icculus.org.
|
||||
|
||||
|
||||
|
||||
OTHER PLATFORMS:
|
||||
|
||||
Many Unix-like platforms might "just work" with CMake. Some of these platforms
|
||||
are known to have worked at one time, but have not been heavily tested, if
|
||||
tested at all. PhysicsFS is, as far as we know, 64-bit and byteorder clean,
|
||||
and is known to compile on several compilers across many platforms. To
|
||||
implement a new platform or archiver, please read the heavily-commented
|
||||
physfs_internal.h and look in the platform/ and archiver/ directories for
|
||||
examples.
|
||||
|
||||
--ryan. (icculus@icculus.org)
|
||||
|
||||
44
project/jni/physfs/LICENSE.txt
Normal file
44
project/jni/physfs/LICENSE.txt
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
Copyright (c) 2001-2011 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
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
|
||||
|
||||
|
||||
|
||||
Notes, separate from the license. This is not legal advice.
|
||||
|
||||
Versions of PhysicsFS prior to 0.1.9 are licensed under the GNU Lesser General
|
||||
Public License, which restricts you significantly more. For your own safety,
|
||||
please make sure you've got 0.1.9 or later if you plan to use physfs in a
|
||||
commercial or closed-source project.
|
||||
|
||||
Optional pieces of PhysicsFS may fall under other licenses, please consult
|
||||
your lawyer for legal advice, which this is not...
|
||||
|
||||
zlib: if you enable ZIP archive support, PhysicsFS uses zlib. Its license
|
||||
requirements are identical to PhysicsFS.
|
||||
Please see zlib123/README for details.
|
||||
|
||||
lzma: if you enable LZMA (7zip) support, PhysicsFS uses the lzma sdk.
|
||||
It uses the LGPL license, with exceptions for closed-source programs.
|
||||
Please see lzma/lzma.txt for details.
|
||||
|
||||
45
project/jni/physfs/TODO.txt
Normal file
45
project/jni/physfs/TODO.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
Stuff that needs to be done and wishlist:
|
||||
|
||||
These are in no particular order.
|
||||
Some might be dupes, some might be done already.
|
||||
|
||||
UNICODE:
|
||||
- OS/2: Codepages. No full Unicode in the filesystem, but we can probably make
|
||||
a conversion effort.
|
||||
|
||||
|
||||
Stuff:
|
||||
- Other archivers: perhaps tar(.gz|.bz2), RPM, ARJ, etc. These are less
|
||||
important, since streaming archives aren't of much value to games (which
|
||||
is why zipfiles are king: random access), but it could have uses for, say,
|
||||
an installer/updater.
|
||||
- Reduce malloc() pressure all over the place. We fragment memory like mad.
|
||||
- profile string list interpolation.
|
||||
- We have two different ways to find dir entries in zip.c.
|
||||
- Do symlinks in zip archiver work when they point to dirs?
|
||||
- Enable more warnings?
|
||||
- Use __cdecl in physfs.h?
|
||||
- Look for FIXMEs (many marked with "!!!" in comments).
|
||||
- Find some way to relax or remove the security model for external tools.
|
||||
- OSX shouldn't use ~/.app for userdir.
|
||||
- fscanf and fprintf support in extras dir.
|
||||
- Why do we call it openArchive and dirClose?
|
||||
- Sanity check byte order at runtime.
|
||||
- Memory locking?
|
||||
- Find a better name than dvoid and fvoid.
|
||||
- Can windows.c and pocketpc.c get merged?
|
||||
- There's so much cut-and-paste between archivers...can this be reduced?
|
||||
- General code audit.
|
||||
- Multiple write dirs with mount points?
|
||||
- Deprecate PHYSFS_setSaneConfig and move it to extras?
|
||||
- Why is physfsrwops.c cut-and-pasted into the ruby bindings?
|
||||
- Replace code from SDL...
|
||||
- Should file enumeration return an error or set error state?
|
||||
- Need "getmountpoint" command in test_physfs.c ...
|
||||
- Look for calloc() calls that aren't going through the allocation hooks.
|
||||
- Write up a simple HOWTO on embedding physicsfs in another project.
|
||||
- Archivers need abstracted i/o to read from memory or files (archives in archives?)
|
||||
- Probably other stuff. Requests and recommendations are welcome.
|
||||
|
||||
// end of TODO.txt ...
|
||||
|
||||
283
project/jni/physfs/archivers/dir.c
Normal file
283
project/jni/physfs/archivers/dir.c
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Standard directory I/O support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
static PHYSFS_sint64 DIR_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
PHYSFS_sint64 retval;
|
||||
retval = __PHYSFS_platformRead(opaque, buffer, objSize, objCount);
|
||||
return(retval);
|
||||
} /* DIR_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 DIR_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
PHYSFS_sint64 retval;
|
||||
retval = __PHYSFS_platformWrite(opaque, buffer, objSize, objCount);
|
||||
return(retval);
|
||||
} /* DIR_write */
|
||||
|
||||
|
||||
static int DIR_eof(fvoid *opaque)
|
||||
{
|
||||
return(__PHYSFS_platformEOF(opaque));
|
||||
} /* DIR_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 DIR_tell(fvoid *opaque)
|
||||
{
|
||||
return(__PHYSFS_platformTell(opaque));
|
||||
} /* DIR_tell */
|
||||
|
||||
|
||||
static int DIR_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
return(__PHYSFS_platformSeek(opaque, offset));
|
||||
} /* DIR_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 DIR_fileLength(fvoid *opaque)
|
||||
{
|
||||
return(__PHYSFS_platformFileLength(opaque));
|
||||
} /* DIR_fileLength */
|
||||
|
||||
|
||||
static int DIR_fileClose(fvoid *opaque)
|
||||
{
|
||||
/*
|
||||
* we manually flush the buffer, since that's the place a close will
|
||||
* most likely fail, but that will leave the file handle in an undefined
|
||||
* state if it fails. Flush failures we can recover from.
|
||||
*/
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformFlush(opaque), NULL, 0);
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(opaque), NULL, 0);
|
||||
return(1);
|
||||
} /* DIR_fileClose */
|
||||
|
||||
|
||||
static int DIR_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
/* directories ARE archives in this driver... */
|
||||
return(__PHYSFS_platformIsDirectory(filename));
|
||||
} /* DIR_isArchive */
|
||||
|
||||
|
||||
static void *DIR_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
const char *dirsep = PHYSFS_getDirSeparator();
|
||||
char *retval = NULL;
|
||||
size_t namelen = strlen(name);
|
||||
size_t seplen = strlen(dirsep);
|
||||
|
||||
/* !!! FIXME: when is this not called right before openArchive? */
|
||||
BAIL_IF_MACRO(!DIR_isArchive(name, forWriting),
|
||||
ERR_UNSUPPORTED_ARCHIVE, 0);
|
||||
|
||||
retval = allocator.Malloc(namelen + seplen + 1);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
/* make sure there's a dir separator at the end of the string */
|
||||
strcpy(retval, name);
|
||||
if (strcmp((name + namelen) - seplen, dirsep) != 0)
|
||||
strcat(retval, dirsep);
|
||||
|
||||
return(retval);
|
||||
} /* DIR_openArchive */
|
||||
|
||||
|
||||
static void DIR_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
char *d = __PHYSFS_platformCvtToDependent((char *)opaque, dname, NULL);
|
||||
if (d != NULL)
|
||||
{
|
||||
__PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
|
||||
origdir, callbackdata);
|
||||
allocator.Free(d);
|
||||
} /* if */
|
||||
} /* DIR_enumerateFiles */
|
||||
|
||||
|
||||
static int DIR_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
||||
retval = __PHYSFS_platformExists(f);
|
||||
allocator.Free(f);
|
||||
return(retval);
|
||||
} /* DIR_exists */
|
||||
|
||||
|
||||
static int DIR_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval = 0;
|
||||
|
||||
BAIL_IF_MACRO(d == NULL, NULL, 0);
|
||||
*fileExists = __PHYSFS_platformExists(d);
|
||||
if (*fileExists)
|
||||
retval = __PHYSFS_platformIsDirectory(d);
|
||||
allocator.Free(d);
|
||||
return(retval);
|
||||
} /* DIR_isDirectory */
|
||||
|
||||
|
||||
static int DIR_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval = 0;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
||||
*fileExists = __PHYSFS_platformExists(f);
|
||||
if (*fileExists)
|
||||
retval = __PHYSFS_platformIsSymLink(f);
|
||||
allocator.Free(f);
|
||||
return(retval);
|
||||
} /* DIR_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 DIR_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
BAIL_IF_MACRO(d == NULL, NULL, 0);
|
||||
*fileExists = __PHYSFS_platformExists(d);
|
||||
if (*fileExists)
|
||||
retval = __PHYSFS_platformGetLastModTime(d);
|
||||
allocator.Free(d);
|
||||
return(retval);
|
||||
} /* DIR_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *doOpen(dvoid *opaque, const char *name,
|
||||
void *(*openFunc)(const char *filename),
|
||||
int *fileExists)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
void *rc = NULL;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, NULL);
|
||||
|
||||
if (fileExists != NULL)
|
||||
{
|
||||
*fileExists = __PHYSFS_platformExists(f);
|
||||
if (!(*fileExists))
|
||||
{
|
||||
allocator.Free(f);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
rc = openFunc(f);
|
||||
allocator.Free(f);
|
||||
|
||||
return((fvoid *) rc);
|
||||
} /* doOpen */
|
||||
|
||||
|
||||
static fvoid *DIR_openRead(dvoid *opaque, const char *fnm, int *exist)
|
||||
{
|
||||
return(doOpen(opaque, fnm, __PHYSFS_platformOpenRead, exist));
|
||||
} /* DIR_openRead */
|
||||
|
||||
|
||||
static fvoid *DIR_openWrite(dvoid *opaque, const char *filename)
|
||||
{
|
||||
return(doOpen(opaque, filename, __PHYSFS_platformOpenWrite, NULL));
|
||||
} /* DIR_openWrite */
|
||||
|
||||
|
||||
static fvoid *DIR_openAppend(dvoid *opaque, const char *filename)
|
||||
{
|
||||
return(doOpen(opaque, filename, __PHYSFS_platformOpenAppend, NULL));
|
||||
} /* DIR_openAppend */
|
||||
|
||||
|
||||
static int DIR_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
||||
retval = __PHYSFS_platformDelete(f);
|
||||
allocator.Free(f);
|
||||
return(retval);
|
||||
} /* DIR_remove */
|
||||
|
||||
|
||||
static int DIR_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
||||
retval = __PHYSFS_platformMkDir(f);
|
||||
allocator.Free(f);
|
||||
return(retval);
|
||||
} /* DIR_mkdir */
|
||||
|
||||
|
||||
static void DIR_dirClose(dvoid *opaque)
|
||||
{
|
||||
allocator.Free(opaque);
|
||||
} /* DIR_dirClose */
|
||||
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_DIR =
|
||||
{
|
||||
"",
|
||||
DIR_ARCHIVE_DESCRIPTION,
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_DIR,
|
||||
DIR_isArchive, /* isArchive() method */
|
||||
DIR_openArchive, /* openArchive() method */
|
||||
DIR_enumerateFiles, /* enumerateFiles() method */
|
||||
DIR_exists, /* exists() method */
|
||||
DIR_isDirectory, /* isDirectory() method */
|
||||
DIR_isSymLink, /* isSymLink() method */
|
||||
DIR_getLastModTime, /* getLastModTime() method */
|
||||
DIR_openRead, /* openRead() method */
|
||||
DIR_openWrite, /* openWrite() method */
|
||||
DIR_openAppend, /* openAppend() method */
|
||||
DIR_remove, /* remove() method */
|
||||
DIR_mkdir, /* mkdir() method */
|
||||
DIR_dirClose, /* dirClose() method */
|
||||
DIR_read, /* read() method */
|
||||
DIR_write, /* write() method */
|
||||
DIR_eof, /* eof() method */
|
||||
DIR_tell, /* tell() method */
|
||||
DIR_seek, /* seek() method */
|
||||
DIR_fileLength, /* fileLength() method */
|
||||
DIR_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
/* end of dir.c ... */
|
||||
|
||||
475
project/jni/physfs/archivers/grp.c
Normal file
475
project/jni/physfs/archivers/grp.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
* GRP support routines for PhysicsFS.
|
||||
*
|
||||
* This driver handles BUILD engine archives ("groupfiles"). This format
|
||||
* (but not this driver) was put together by Ken Silverman.
|
||||
*
|
||||
* The format is simple enough. In Ken's words:
|
||||
*
|
||||
* What's the .GRP file format?
|
||||
*
|
||||
* The ".grp" file format is just a collection of a lot of files stored
|
||||
* into 1 big one. I tried to make the format as simple as possible: The
|
||||
* first 12 bytes contains my name, "KenSilverman". The next 4 bytes is
|
||||
* the number of files that were compacted into the group file. Then for
|
||||
* each file, there is a 16 byte structure, where the first 12 bytes are
|
||||
* the filename, and the last 4 bytes are the file's size. The rest of
|
||||
* the group file is just the raw data packed one after the other in the
|
||||
* same order as the list of files.
|
||||
*
|
||||
* (That info is from http://www.advsys.net/ken/build.htm ...)
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_GRP)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[13];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} GRPentry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
GRPentry *entries;
|
||||
} GRPinfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
GRPentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} GRPfileinfo;
|
||||
|
||||
|
||||
static void GRP_dirClose(dvoid *opaque)
|
||||
{
|
||||
GRPinfo *info = ((GRPinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* GRP_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
GRPentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* GRP_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* GRP_write */
|
||||
|
||||
|
||||
static int GRP_eof(fvoid *opaque)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
GRPentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* GRP_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_tell(fvoid *opaque)
|
||||
{
|
||||
return(((GRPfileinfo *) opaque)->curPos);
|
||||
} /* GRP_tell */
|
||||
|
||||
|
||||
static int GRP_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
GRPentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* GRP_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_fileLength(fvoid *opaque)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* GRP_fileLength */
|
||||
|
||||
|
||||
static int GRP_fileClose(fvoid *opaque)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* GRP_fileClose */
|
||||
|
||||
|
||||
static int grp_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count)
|
||||
{
|
||||
PHYSFS_uint8 buf[12];
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, buf, 12, 1) != 1)
|
||||
goto openGrp_failed;
|
||||
|
||||
if (memcmp(buf, "KenSilverman", 12) != 0)
|
||||
{
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
goto openGrp_failed;
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openGrp_failed;
|
||||
|
||||
*count = PHYSFS_swapULE32(*count);
|
||||
|
||||
return(1);
|
||||
|
||||
openGrp_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* grp_open */
|
||||
|
||||
|
||||
static int GRP_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount;
|
||||
int retval = grp_open(filename, forWriting, &fh, &fileCount);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* GRP_isArchive */
|
||||
|
||||
|
||||
static int grp_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const GRPentry *a = (const GRPentry *) _a;
|
||||
return(strcmp(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* grp_entry_cmp */
|
||||
|
||||
|
||||
static void grp_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
GRPentry tmp;
|
||||
GRPentry *first = &(((GRPentry *) _a)[one]);
|
||||
GRPentry *second = &(((GRPentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (GRPentry));
|
||||
memcpy(first, second, sizeof (GRPentry));
|
||||
memcpy(second, &tmp, sizeof (GRPentry));
|
||||
} /* if */
|
||||
} /* grp_entry_swap */
|
||||
|
||||
|
||||
static int grp_load_entries(const char *name, int forWriting, GRPinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
PHYSFS_uint32 location = 16; /* sizeof sig. */
|
||||
GRPentry *entry;
|
||||
char *ptr;
|
||||
|
||||
BAIL_IF_MACRO(!grp_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (GRPentry *) allocator.Malloc(sizeof(GRPentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
location += (16 * fileCount);
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
if (__PHYSFS_platformRead(fh, &entry->name, 12, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->name[12] = '\0'; /* name isn't null-terminated in file. */
|
||||
if ((ptr = strchr(entry->name, ' ')) != NULL)
|
||||
*ptr = '\0'; /* trim extra spaces. */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = location;
|
||||
location += entry->size;
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
grp_entry_cmp, grp_entry_swap);
|
||||
return(1);
|
||||
} /* grp_load_entries */
|
||||
|
||||
|
||||
static void *GRP_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
GRPinfo *info = (GRPinfo *) allocator.Malloc(sizeof (GRPinfo));
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
memset(info, '\0', sizeof (GRPinfo));
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, GRP_openArchive_failed);
|
||||
|
||||
if (!grp_load_entries(name, forWriting, info))
|
||||
goto GRP_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
|
||||
return(info);
|
||||
|
||||
GRP_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* GRP_openArchive */
|
||||
|
||||
|
||||
static void GRP_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
/* no directories in GRP files. */
|
||||
if (*dname == '\0')
|
||||
{
|
||||
GRPinfo *info = (GRPinfo *) opaque;
|
||||
GRPentry *entry = info->entries;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
cb(callbackdata, origdir, entry->name);
|
||||
} /* if */
|
||||
} /* GRP_enumerateFiles */
|
||||
|
||||
|
||||
static GRPentry *grp_find_entry(GRPinfo *info, const char *name)
|
||||
{
|
||||
char *ptr = strchr(name, '.');
|
||||
GRPentry *a = info->entries;
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Rule out filenames to avoid unneeded processing...no dirs,
|
||||
* big filenames, or extensions > 3 chars.
|
||||
*/
|
||||
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
rc = strcmp(name, a[middle].name);
|
||||
if (rc == 0) /* found it! */
|
||||
return(&a[middle]);
|
||||
else if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* grp_find_entry */
|
||||
|
||||
|
||||
static int GRP_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
return(grp_find_entry((GRPinfo *) opaque, name) != NULL);
|
||||
} /* GRP_exists */
|
||||
|
||||
|
||||
static int GRP_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = GRP_exists(opaque, name);
|
||||
return(0); /* never directories in a groupfile. */
|
||||
} /* GRP_isDirectory */
|
||||
|
||||
|
||||
static int GRP_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = GRP_exists(opaque, name);
|
||||
return(0); /* never symlinks in a groupfile. */
|
||||
} /* GRP_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
GRPinfo *info = (GRPinfo *) opaque;
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
*fileExists = (grp_find_entry(info, name) != NULL);
|
||||
if (*fileExists) /* use time of GRP itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* GRP_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *GRP_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
GRPinfo *info = (GRPinfo *) opaque;
|
||||
GRPfileinfo *finfo;
|
||||
GRPentry *entry;
|
||||
|
||||
entry = grp_find_entry(info, fnm);
|
||||
*fileExists = (entry != NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
||||
|
||||
finfo = (GRPfileinfo *) allocator.Malloc(sizeof (GRPfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* GRP_openRead */
|
||||
|
||||
|
||||
static fvoid *GRP_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* GRP_openWrite */
|
||||
|
||||
|
||||
static fvoid *GRP_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* GRP_openAppend */
|
||||
|
||||
|
||||
static int GRP_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* GRP_remove */
|
||||
|
||||
|
||||
static int GRP_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* GRP_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_GRP =
|
||||
{
|
||||
"GRP",
|
||||
GRP_ARCHIVE_DESCRIPTION,
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_GRP,
|
||||
GRP_isArchive, /* isArchive() method */
|
||||
GRP_openArchive, /* openArchive() method */
|
||||
GRP_enumerateFiles, /* enumerateFiles() method */
|
||||
GRP_exists, /* exists() method */
|
||||
GRP_isDirectory, /* isDirectory() method */
|
||||
GRP_isSymLink, /* isSymLink() method */
|
||||
GRP_getLastModTime, /* getLastModTime() method */
|
||||
GRP_openRead, /* openRead() method */
|
||||
GRP_openWrite, /* openWrite() method */
|
||||
GRP_openAppend, /* openAppend() method */
|
||||
GRP_remove, /* remove() method */
|
||||
GRP_mkdir, /* mkdir() method */
|
||||
GRP_dirClose, /* dirClose() method */
|
||||
GRP_read, /* read() method */
|
||||
GRP_write, /* write() method */
|
||||
GRP_eof, /* eof() method */
|
||||
GRP_tell, /* tell() method */
|
||||
GRP_seek, /* seek() method */
|
||||
GRP_fileLength, /* fileLength() method */
|
||||
GRP_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_GRP */
|
||||
|
||||
/* end of grp.c ... */
|
||||
|
||||
514
project/jni/physfs/archivers/hog.c
Normal file
514
project/jni/physfs/archivers/hog.c
Normal file
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* HOG support routines for PhysicsFS.
|
||||
*
|
||||
* This driver handles Descent I/II HOG archives.
|
||||
*
|
||||
* The format is very simple:
|
||||
*
|
||||
* The file always starts with the 3-byte signature "DHF" (Descent
|
||||
* HOG file). After that the files of a HOG are just attached after
|
||||
* another, divided by a 17 bytes header, which specifies the name
|
||||
* and length (in bytes) of the forthcoming file! So you just read
|
||||
* the header with its information of how big the following file is,
|
||||
* and then skip exact that number of bytes to get to the next file
|
||||
* in that HOG.
|
||||
*
|
||||
* char sig[3] = {'D', 'H', 'F'}; // "DHF"=Descent HOG File
|
||||
*
|
||||
* struct {
|
||||
* char file_name[13]; // Filename, padded to 13 bytes with 0s
|
||||
* int file_size; // filesize in bytes
|
||||
* char data[file_size]; // The file data
|
||||
* } FILE_STRUCT; // Repeated until the end of the file.
|
||||
*
|
||||
* (That info is from http://www.descent2.com/ddn/specs/hog/)
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Bradley Bell.
|
||||
* Based on grp.c by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_HOG)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
/*
|
||||
* One HOGentry is kept for each file in an open HOG archive.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char name[13];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} HOGentry;
|
||||
|
||||
/*
|
||||
* One HOGinfo is kept for each open HOG archive.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
HOGentry *entries;
|
||||
} HOGinfo;
|
||||
|
||||
/*
|
||||
* One HOGfileinfo is kept for each open file in a HOG archive.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
HOGentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} HOGfileinfo;
|
||||
|
||||
|
||||
static void HOG_dirClose(dvoid *opaque)
|
||||
{
|
||||
HOGinfo *info = ((HOGinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* HOG_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
HOGentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* HOG_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* HOG_write */
|
||||
|
||||
|
||||
static int HOG_eof(fvoid *opaque)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
HOGentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* HOG_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_tell(fvoid *opaque)
|
||||
{
|
||||
return(((HOGfileinfo *) opaque)->curPos);
|
||||
} /* HOG_tell */
|
||||
|
||||
|
||||
static int HOG_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
HOGentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* HOG_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_fileLength(fvoid *opaque)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* HOG_fileLength */
|
||||
|
||||
|
||||
static int HOG_fileClose(fvoid *opaque)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* HOG_fileClose */
|
||||
|
||||
|
||||
static int hog_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count)
|
||||
{
|
||||
PHYSFS_uint8 buf[13];
|
||||
PHYSFS_uint32 size;
|
||||
PHYSFS_sint64 pos;
|
||||
|
||||
*count = 0;
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, buf, 3, 1) != 1)
|
||||
goto openHog_failed;
|
||||
|
||||
if (memcmp(buf, "DHF", 3) != 0)
|
||||
{
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
goto openHog_failed;
|
||||
} /* if */
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (__PHYSFS_platformRead(*fh, buf, 13, 1) != 1)
|
||||
break; /* eof here is ok */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, &size, 4, 1) != 1)
|
||||
goto openHog_failed;
|
||||
|
||||
size = PHYSFS_swapULE32(size);
|
||||
|
||||
(*count)++;
|
||||
|
||||
/* Skip over entry... */
|
||||
pos = __PHYSFS_platformTell(*fh);
|
||||
if (pos == -1)
|
||||
goto openHog_failed;
|
||||
if (!__PHYSFS_platformSeek(*fh, pos + size))
|
||||
goto openHog_failed;
|
||||
} /* while */
|
||||
|
||||
/* Rewind to start of entries... */
|
||||
if (!__PHYSFS_platformSeek(*fh, 3))
|
||||
goto openHog_failed;
|
||||
|
||||
return(1);
|
||||
|
||||
openHog_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* hog_open */
|
||||
|
||||
|
||||
static int HOG_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount;
|
||||
int retval = hog_open(filename, forWriting, &fh, &fileCount);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* HOG_isArchive */
|
||||
|
||||
|
||||
static int hog_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const HOGentry *a = (const HOGentry *) _a;
|
||||
return(__PHYSFS_stricmpASCII(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* hog_entry_cmp */
|
||||
|
||||
|
||||
static void hog_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
HOGentry tmp;
|
||||
HOGentry *first = &(((HOGentry *) _a)[one]);
|
||||
HOGentry *second = &(((HOGentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (HOGentry));
|
||||
memcpy(first, second, sizeof (HOGentry));
|
||||
memcpy(second, &tmp, sizeof (HOGentry));
|
||||
} /* if */
|
||||
} /* hog_entry_swap */
|
||||
|
||||
|
||||
static int hog_load_entries(const char *name, int forWriting, HOGinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
HOGentry *entry;
|
||||
|
||||
BAIL_IF_MACRO(!hog_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (HOGentry *) allocator.Malloc(sizeof(HOGentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = (unsigned int) __PHYSFS_platformTell(fh);
|
||||
if (entry->startPos == -1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Skip over entry */
|
||||
if (!__PHYSFS_platformSeek(fh, entry->startPos + entry->size))
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
}
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
hog_entry_cmp, hog_entry_swap);
|
||||
return(1);
|
||||
} /* hog_load_entries */
|
||||
|
||||
|
||||
static void *HOG_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
HOGinfo *info = (HOGinfo *) allocator.Malloc(sizeof (HOGinfo));
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
memset(info, '\0', sizeof (HOGinfo));
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, HOG_openArchive_failed);
|
||||
|
||||
if (!hog_load_entries(name, forWriting, info))
|
||||
goto HOG_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
|
||||
return(info);
|
||||
|
||||
HOG_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* HOG_openArchive */
|
||||
|
||||
|
||||
static void HOG_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
/* no directories in HOG files. */
|
||||
if (*dname == '\0')
|
||||
{
|
||||
HOGinfo *info = (HOGinfo *) opaque;
|
||||
HOGentry *entry = info->entries;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
cb(callbackdata, origdir, entry->name);
|
||||
} /* if */
|
||||
} /* HOG_enumerateFiles */
|
||||
|
||||
|
||||
static HOGentry *hog_find_entry(HOGinfo *info, const char *name)
|
||||
{
|
||||
char *ptr = strchr(name, '.');
|
||||
HOGentry *a = info->entries;
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Rule out filenames to avoid unneeded processing...no dirs,
|
||||
* big filenames, or extensions > 3 chars.
|
||||
*/
|
||||
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
rc = __PHYSFS_stricmpASCII(name, a[middle].name);
|
||||
if (rc == 0) /* found it! */
|
||||
return(&a[middle]);
|
||||
else if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* hog_find_entry */
|
||||
|
||||
|
||||
static int HOG_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
return(hog_find_entry(((HOGinfo *) opaque), name) != NULL);
|
||||
} /* HOG_exists */
|
||||
|
||||
|
||||
static int HOG_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = HOG_exists(opaque, name);
|
||||
return(0); /* never directories in a groupfile. */
|
||||
} /* HOG_isDirectory */
|
||||
|
||||
|
||||
static int HOG_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = HOG_exists(opaque, name);
|
||||
return(0); /* never symlinks in a groupfile. */
|
||||
} /* HOG_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
HOGinfo *info = ((HOGinfo *) opaque);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
*fileExists = (hog_find_entry(info, name) != NULL);
|
||||
if (*fileExists) /* use time of HOG itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* HOG_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *HOG_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
HOGinfo *info = ((HOGinfo *) opaque);
|
||||
HOGfileinfo *finfo;
|
||||
HOGentry *entry;
|
||||
|
||||
entry = hog_find_entry(info, fnm);
|
||||
*fileExists = (entry != NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
||||
|
||||
finfo = (HOGfileinfo *) allocator.Malloc(sizeof (HOGfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* HOG_openRead */
|
||||
|
||||
|
||||
static fvoid *HOG_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* HOG_openWrite */
|
||||
|
||||
|
||||
static fvoid *HOG_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* HOG_openAppend */
|
||||
|
||||
|
||||
static int HOG_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* HOG_remove */
|
||||
|
||||
|
||||
static int HOG_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* HOG_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_HOG =
|
||||
{
|
||||
"HOG",
|
||||
HOG_ARCHIVE_DESCRIPTION,
|
||||
"Bradley Bell <btb@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_HOG,
|
||||
HOG_isArchive, /* isArchive() method */
|
||||
HOG_openArchive, /* openArchive() method */
|
||||
HOG_enumerateFiles, /* enumerateFiles() method */
|
||||
HOG_exists, /* exists() method */
|
||||
HOG_isDirectory, /* isDirectory() method */
|
||||
HOG_isSymLink, /* isSymLink() method */
|
||||
HOG_getLastModTime, /* getLastModTime() method */
|
||||
HOG_openRead, /* openRead() method */
|
||||
HOG_openWrite, /* openWrite() method */
|
||||
HOG_openAppend, /* openAppend() method */
|
||||
HOG_remove, /* remove() method */
|
||||
HOG_mkdir, /* mkdir() method */
|
||||
HOG_dirClose, /* dirClose() method */
|
||||
HOG_read, /* read() method */
|
||||
HOG_write, /* write() method */
|
||||
HOG_eof, /* eof() method */
|
||||
HOG_tell, /* tell() method */
|
||||
HOG_seek, /* seek() method */
|
||||
HOG_fileLength, /* fileLength() method */
|
||||
HOG_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_HOG */
|
||||
|
||||
/* end of hog.c ... */
|
||||
|
||||
736
project/jni/physfs/archivers/lzma.c
Normal file
736
project/jni/physfs/archivers/lzma.c
Normal file
@@ -0,0 +1,736 @@
|
||||
/*
|
||||
* LZMA support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file lzma.txt in the lzma/ directory.
|
||||
*
|
||||
* This file was written by Dennis Schridde, with some peeking at "7zMain.c"
|
||||
* by Igor Pavlov.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_7Z)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
#include "lzma/C/7zCrc.h"
|
||||
#include "lzma/C/Archive/7z/7zIn.h"
|
||||
#include "lzma/C/Archive/7z/7zExtract.h"
|
||||
|
||||
|
||||
/* 7z internal from 7zIn.c */
|
||||
extern int TestSignatureCandidate(Byte *testBytes);
|
||||
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
# define BUFFER_SIZE (1 << 12)
|
||||
#endif /* _LZMA_IN_CB */
|
||||
|
||||
|
||||
/*
|
||||
* Carries filestream metadata through 7z
|
||||
*/
|
||||
typedef struct _FileInputStream
|
||||
{
|
||||
ISzAlloc allocImp; /* Allocation implementation, used by 7z */
|
||||
ISzAlloc allocTempImp; /* Temporary allocation implementation, used by 7z */
|
||||
ISzInStream inStream; /* Input stream with read callbacks, used by 7z */
|
||||
void *file; /* Filehandle, used by read implementation */
|
||||
#ifdef _LZMA_IN_CB
|
||||
Byte buffer[BUFFER_SIZE]; /* Buffer, used by read implementation */
|
||||
#endif /* _LZMA_IN_CB */
|
||||
} FileInputStream;
|
||||
|
||||
/*
|
||||
* In the 7z format archives are splited into blocks, those are called folders
|
||||
* Set by LZMA_read()
|
||||
*/
|
||||
typedef struct _LZMAfolder
|
||||
{
|
||||
PHYSFS_uint32 index; /* Index of folder in archive */
|
||||
PHYSFS_uint32 references; /* Number of files using this block */
|
||||
PHYSFS_uint8 *cache; /* Cached folder */
|
||||
size_t size; /* Size of folder */
|
||||
} LZMAfolder;
|
||||
|
||||
/*
|
||||
* Set by LZMA_openArchive(), except folder which gets it's values
|
||||
* in LZMA_read()
|
||||
*/
|
||||
typedef struct _LZMAarchive
|
||||
{
|
||||
struct _LZMAfile *files; /* Array of files, size == archive->db.Database.NumFiles */
|
||||
LZMAfolder *folders; /* Array of folders, size == archive->db.Database.NumFolders */
|
||||
CArchiveDatabaseEx db; /* For 7z: Database */
|
||||
FileInputStream stream; /* For 7z: Input file incl. read and seek callbacks */
|
||||
} LZMAarchive;
|
||||
|
||||
/* Set by LZMA_openArchive(), except offset which is set by LZMA_read() */
|
||||
typedef struct _LZMAfile
|
||||
{
|
||||
PHYSFS_uint32 index; /* Index of file in archive */
|
||||
LZMAarchive *archive; /* Link to corresponding archive */
|
||||
LZMAfolder *folder; /* Link to corresponding folder */
|
||||
CFileItem *item; /* For 7z: File info, eg. name, size */
|
||||
size_t offset; /* Offset in folder */
|
||||
size_t position; /* Current "virtual" position in file */
|
||||
} LZMAfile;
|
||||
|
||||
|
||||
/* Memory management implementations to be passed to 7z */
|
||||
|
||||
static void *SzAllocPhysicsFS(size_t size)
|
||||
{
|
||||
return ((size == 0) ? NULL : allocator.Malloc(size));
|
||||
} /* SzAllocPhysicsFS */
|
||||
|
||||
|
||||
static void SzFreePhysicsFS(void *address)
|
||||
{
|
||||
if (address != NULL)
|
||||
allocator.Free(address);
|
||||
} /* SzFreePhysicsFS */
|
||||
|
||||
|
||||
/* Filesystem implementations to be passed to 7z */
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
|
||||
/*
|
||||
* Read implementation, to be passed to 7z
|
||||
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
|
||||
*/
|
||||
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxReqSize,
|
||||
size_t *processedSize)
|
||||
{
|
||||
FileInputStream *s = (FileInputStream *)(object - offsetof(FileInputStream, inStream)); /* HACK! */
|
||||
PHYSFS_sint64 processedSizeLoc = 0;
|
||||
|
||||
if (maxReqSize > BUFFER_SIZE)
|
||||
maxReqSize = BUFFER_SIZE;
|
||||
processedSizeLoc = __PHYSFS_platformRead(s->file, s->buffer, 1, maxReqSize);
|
||||
*buffer = s->buffer;
|
||||
if (processedSize != NULL)
|
||||
*processedSize = (size_t) processedSizeLoc;
|
||||
|
||||
return SZ_OK;
|
||||
} /* SzFileReadImp */
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Read implementation, to be passed to 7z
|
||||
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
|
||||
*/
|
||||
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size,
|
||||
size_t *processedSize)
|
||||
{
|
||||
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
|
||||
size_t processedSizeLoc = __PHYSFS_platformRead(s->file, buffer, 1, size);
|
||||
if (processedSize != 0)
|
||||
*processedSize = processedSizeLoc;
|
||||
return SZ_OK;
|
||||
} /* SzFileReadImp */
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Seek implementation, to be passed to 7z
|
||||
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
|
||||
*/
|
||||
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
|
||||
{
|
||||
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
|
||||
if (__PHYSFS_platformSeek(s->file, (PHYSFS_uint64) pos))
|
||||
return SZ_OK;
|
||||
return SZE_FAIL;
|
||||
} /* SzFileSeekImp */
|
||||
|
||||
|
||||
/*
|
||||
* Translate Microsoft FILETIME (used by 7zip) into UNIX timestamp
|
||||
*/
|
||||
static PHYSFS_sint64 lzma_filetime_to_unix_timestamp(CArchiveFileTime *ft)
|
||||
{
|
||||
/* MS counts in nanoseconds ... */
|
||||
const PHYSFS_uint64 FILETIME_NANOTICKS_PER_SECOND = __PHYSFS_UI64(10000000);
|
||||
/* MS likes to count seconds since 01.01.1601 ... */
|
||||
const PHYSFS_uint64 FILETIME_UNIX_DIFF = __PHYSFS_UI64(11644473600);
|
||||
|
||||
PHYSFS_uint64 filetime = ft->Low | ((PHYSFS_uint64)ft->High << 32);
|
||||
return filetime/FILETIME_NANOTICKS_PER_SECOND - FILETIME_UNIX_DIFF;
|
||||
} /* lzma_filetime_to_unix_timestamp */
|
||||
|
||||
|
||||
/*
|
||||
* Compare a file with a given name, C89 stdlib variant
|
||||
* Used for sorting
|
||||
*/
|
||||
static int lzma_file_cmp_stdlib(const void *key, const void *object)
|
||||
{
|
||||
const char *name = (const char *) key;
|
||||
LZMAfile *file = (LZMAfile *) object;
|
||||
return(strcmp(name, file->item->Name));
|
||||
} /* lzma_file_cmp_posix */
|
||||
|
||||
|
||||
/*
|
||||
* Compare two files with each other based on the name
|
||||
* Used for sorting
|
||||
*/
|
||||
static int lzma_file_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
LZMAfile *files = (LZMAfile *) _a;
|
||||
return(strcmp(files[one].item->Name, files[two].item->Name));
|
||||
} /* lzma_file_cmp */
|
||||
|
||||
|
||||
/*
|
||||
* Swap two entries in the file array
|
||||
*/
|
||||
static void lzma_file_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
LZMAfile tmp;
|
||||
LZMAfile *first = &(((LZMAfile *) _a)[one]);
|
||||
LZMAfile *second = &(((LZMAfile *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (LZMAfile));
|
||||
memcpy(first, second, sizeof (LZMAfile));
|
||||
memcpy(second, &tmp, sizeof (LZMAfile));
|
||||
} /* lzma_file_swap */
|
||||
|
||||
|
||||
/*
|
||||
* Find entry 'name' in 'archive'
|
||||
*/
|
||||
static LZMAfile * lzma_find_file(LZMAarchive *archive, const char *name)
|
||||
{
|
||||
LZMAfile *file = bsearch(name, archive->files, archive->db.Database.NumFiles, sizeof(*archive->files), lzma_file_cmp_stdlib); /* FIXME: Should become __PHYSFS_search!!! */
|
||||
|
||||
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
return(file);
|
||||
} /* lzma_find_file */
|
||||
|
||||
|
||||
/*
|
||||
* Load metadata for the file at given index
|
||||
*/
|
||||
static int lzma_file_init(LZMAarchive *archive, PHYSFS_uint32 fileIndex)
|
||||
{
|
||||
LZMAfile *file = &archive->files[fileIndex];
|
||||
PHYSFS_uint32 folderIndex = archive->db.FileIndexToFolderIndexMap[fileIndex];
|
||||
|
||||
file->index = fileIndex; /* Store index into 7z array, since we sort our own. */
|
||||
file->archive = archive;
|
||||
file->folder = (folderIndex != (PHYSFS_uint32)-1 ? &archive->folders[folderIndex] : NULL); /* Directories don't have a folder (they contain no own data...) */
|
||||
file->item = &archive->db.Database.Files[fileIndex]; /* Holds crucial data and is often referenced -> Store link */
|
||||
file->position = 0;
|
||||
file->offset = 0; /* Offset will be set by LZMA_read() */
|
||||
|
||||
return(1);
|
||||
} /* lzma_load_file */
|
||||
|
||||
|
||||
/*
|
||||
* Load metadata for all files
|
||||
*/
|
||||
static int lzma_files_init(LZMAarchive *archive)
|
||||
{
|
||||
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
|
||||
|
||||
for (fileIndex = 0; fileIndex < numFiles; fileIndex++ )
|
||||
{
|
||||
if (!lzma_file_init(archive, fileIndex))
|
||||
{
|
||||
return(0); /* FALSE on failure */
|
||||
}
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_sort(archive->files, numFiles, lzma_file_cmp, lzma_file_swap);
|
||||
|
||||
return(1);
|
||||
} /* lzma_load_files */
|
||||
|
||||
|
||||
/*
|
||||
* Initialise specified archive
|
||||
*/
|
||||
static void lzma_archive_init(LZMAarchive *archive)
|
||||
{
|
||||
memset(archive, 0, sizeof(*archive));
|
||||
|
||||
/* Prepare callbacks for 7z */
|
||||
archive->stream.inStream.Read = SzFileReadImp;
|
||||
archive->stream.inStream.Seek = SzFileSeekImp;
|
||||
|
||||
archive->stream.allocImp.Alloc = SzAllocPhysicsFS;
|
||||
archive->stream.allocImp.Free = SzFreePhysicsFS;
|
||||
|
||||
archive->stream.allocTempImp.Alloc = SzAllocPhysicsFS;
|
||||
archive->stream.allocTempImp.Free = SzFreePhysicsFS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialise archive
|
||||
*/
|
||||
static void lzma_archive_exit(LZMAarchive *archive)
|
||||
{
|
||||
/* Free arrays */
|
||||
allocator.Free(archive->folders);
|
||||
allocator.Free(archive->files);
|
||||
allocator.Free(archive);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrap all 7z calls in this, so the physfs error state is set appropriately.
|
||||
*/
|
||||
static int lzma_err(SZ_RESULT rc)
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case SZ_OK: /* Same as LZMA_RESULT_OK */
|
||||
break;
|
||||
case SZE_DATA_ERROR: /* Same as LZMA_RESULT_DATA_ERROR */
|
||||
__PHYSFS_setError(ERR_DATA_ERROR);
|
||||
break;
|
||||
case SZE_OUTOFMEMORY:
|
||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
||||
break;
|
||||
case SZE_CRC_ERROR:
|
||||
__PHYSFS_setError(ERR_CORRUPTED);
|
||||
break;
|
||||
case SZE_NOTIMPL:
|
||||
__PHYSFS_setError(ERR_NOT_IMPLEMENTED);
|
||||
break;
|
||||
case SZE_FAIL:
|
||||
__PHYSFS_setError(ERR_UNKNOWN_ERROR); /* !!! FIXME: right? */
|
||||
break;
|
||||
case SZE_ARCHIVE_ERROR:
|
||||
__PHYSFS_setError(ERR_CORRUPTED); /* !!! FIXME: right? */
|
||||
break;
|
||||
default:
|
||||
__PHYSFS_setError(ERR_UNKNOWN_ERROR);
|
||||
} /* switch */
|
||||
|
||||
return(rc);
|
||||
} /* lzma_err */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
|
||||
size_t wantedSize = objSize*objCount;
|
||||
size_t remainingSize = file->item->Size - file->position;
|
||||
size_t fileSize = 0;
|
||||
|
||||
BAIL_IF_MACRO(wantedSize == 0, NULL, 0); /* quick rejection. */
|
||||
BAIL_IF_MACRO(remainingSize == 0, ERR_PAST_EOF, 0);
|
||||
|
||||
if (remainingSize < wantedSize)
|
||||
{
|
||||
wantedSize = remainingSize - (remainingSize % objSize);
|
||||
objCount = (PHYSFS_uint32) (remainingSize / objSize);
|
||||
BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */
|
||||
__PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */
|
||||
} /* if */
|
||||
|
||||
/* Only decompress the folder if it is not allready cached */
|
||||
if (file->folder->cache == NULL)
|
||||
{
|
||||
int rc = lzma_err(SzExtract(
|
||||
&file->archive->stream.inStream, /* compressed data */
|
||||
&file->archive->db, /* 7z's database, containing everything */
|
||||
file->index, /* Index into database arrays */
|
||||
/* Index of cached folder, will be changed by SzExtract */
|
||||
&file->folder->index,
|
||||
/* Cache for decompressed folder, allocated/freed by SzExtract */
|
||||
&file->folder->cache,
|
||||
/* Size of cache, will be changed by SzExtract */
|
||||
&file->folder->size,
|
||||
/* Offset of this file inside the cache, set by SzExtract */
|
||||
&file->offset,
|
||||
&fileSize, /* Size of this file */
|
||||
&file->archive->stream.allocImp,
|
||||
&file->archive->stream.allocTempImp));
|
||||
|
||||
if (rc != SZ_OK)
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
/* Copy wanted bytes over from cache to outBuffer */
|
||||
memcpy(outBuffer,
|
||||
(file->folder->cache +
|
||||
file->offset + file->position),
|
||||
wantedSize);
|
||||
file->position += wantedSize; /* Increase virtual position */
|
||||
|
||||
return objCount;
|
||||
} /* LZMA_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_write(fvoid *opaque, const void *buf,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* LZMA_write */
|
||||
|
||||
|
||||
static int LZMA_eof(fvoid *opaque)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
return (file->position >= file->item->Size);
|
||||
} /* LZMA_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_tell(fvoid *opaque)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
return (file->position);
|
||||
} /* LZMA_tell */
|
||||
|
||||
|
||||
static int LZMA_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_SEEK_OUT_OF_RANGE, 0);
|
||||
BAIL_IF_MACRO(offset > file->item->Size, ERR_PAST_EOF, 0);
|
||||
|
||||
file->position = offset; /* We only use a virtual position... */
|
||||
|
||||
return 1;
|
||||
} /* LZMA_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_fileLength(fvoid *opaque)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
return (file->item->Size);
|
||||
} /* LZMA_fileLength */
|
||||
|
||||
|
||||
static int LZMA_fileClose(fvoid *opaque)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
|
||||
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, 0);
|
||||
|
||||
/* Only decrease refcount if someone actually requested this file... Prevents from overflows and close-on-open... */
|
||||
if (file->folder->references > 0)
|
||||
file->folder->references--;
|
||||
if (file->folder->references == 0)
|
||||
{
|
||||
/* Free the cache which might have been allocated by LZMA_read() */
|
||||
allocator.Free(file->folder->cache);
|
||||
file->folder->cache = NULL;
|
||||
}
|
||||
|
||||
return(1);
|
||||
} /* LZMA_fileClose */
|
||||
|
||||
|
||||
static int LZMA_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
PHYSFS_uint8 sig[k7zSignatureSize];
|
||||
void *in;
|
||||
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
in = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(in == NULL, NULL, 0);
|
||||
|
||||
/* Read signature bytes */
|
||||
if (__PHYSFS_platformRead(in, sig, k7zSignatureSize, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(in); /* Don't forget to close the file before returning... */
|
||||
BAIL_MACRO(NULL, 0);
|
||||
}
|
||||
|
||||
__PHYSFS_platformClose(in);
|
||||
|
||||
/* Test whether sig is the 7z signature */
|
||||
return(TestSignatureCandidate(sig));
|
||||
} /* LZMA_isArchive */
|
||||
|
||||
|
||||
static void *LZMA_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
size_t len = 0;
|
||||
LZMAarchive *archive = NULL;
|
||||
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
|
||||
BAIL_IF_MACRO(!LZMA_isArchive(name,forWriting), ERR_UNSUPPORTED_ARCHIVE, 0);
|
||||
|
||||
archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
|
||||
BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
lzma_archive_init(archive);
|
||||
|
||||
if ( (archive->stream.file = __PHYSFS_platformOpenRead(name)) == NULL )
|
||||
{
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
return(NULL); /* Error is set by platformOpenRead! */
|
||||
}
|
||||
|
||||
CrcGenerateTable();
|
||||
SzArDbExInit(&archive->db);
|
||||
if (lzma_err(SzArchiveOpen(&archive->stream.inStream,
|
||||
&archive->db,
|
||||
&archive->stream.allocImp,
|
||||
&archive->stream.allocTempImp)) != SZ_OK)
|
||||
{
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
return NULL; /* Error is set by lzma_err! */
|
||||
} /* if */
|
||||
|
||||
len = archive->db.Database.NumFiles * sizeof (LZMAfile);
|
||||
archive->files = (LZMAfile *) allocator.Malloc(len);
|
||||
if (archive->files == NULL)
|
||||
{
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init with 0 so we know when a folder is already cached
|
||||
* Values will be set by LZMA_openRead()
|
||||
*/
|
||||
memset(archive->files, 0, len);
|
||||
|
||||
len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
|
||||
archive->folders = (LZMAfolder *) allocator.Malloc(len);
|
||||
if (archive->folders == NULL)
|
||||
{
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init with 0 so we know when a folder is already cached
|
||||
* Values will be set by LZMA_read()
|
||||
*/
|
||||
memset(archive->folders, 0, len);
|
||||
|
||||
if(!lzma_files_init(archive))
|
||||
{
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
BAIL_MACRO(ERR_UNKNOWN_ERROR, NULL);
|
||||
}
|
||||
|
||||
return(archive);
|
||||
} /* LZMA_openArchive */
|
||||
|
||||
|
||||
/*
|
||||
* Moved to seperate function so we can use alloca then immediately throw
|
||||
* away the allocated stack space...
|
||||
*/
|
||||
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
||||
const char *odir, const char *str, size_t flen)
|
||||
{
|
||||
char *newstr = __PHYSFS_smallAlloc(flen + 1);
|
||||
if (newstr == NULL)
|
||||
return;
|
||||
|
||||
memcpy(newstr, str, flen);
|
||||
newstr[flen] = '\0';
|
||||
cb(callbackdata, odir, newstr);
|
||||
__PHYSFS_smallFree(newstr);
|
||||
} /* doEnumCallback */
|
||||
|
||||
|
||||
static void LZMA_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
size_t dlen = strlen(dname),
|
||||
dlen_inc = dlen + ((dlen > 0) ? 1 : 0);
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
LZMAfile *file = NULL,
|
||||
*lastFile = &archive->files[archive->db.Database.NumFiles];
|
||||
if (dlen)
|
||||
{
|
||||
file = lzma_find_file(archive, dname);
|
||||
if (file != NULL) /* if 'file' is NULL it should stay so, otherwise errors will not be handled */
|
||||
file += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
file = archive->files;
|
||||
}
|
||||
|
||||
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, );
|
||||
|
||||
while (file < lastFile)
|
||||
{
|
||||
const char * fname = file->item->Name;
|
||||
const char * dirNameEnd = fname + dlen_inc;
|
||||
|
||||
if (strncmp(dname, fname, dlen) != 0) /* Stop after mismatch, archive->files is sorted */
|
||||
break;
|
||||
|
||||
if (strchr(dirNameEnd, '/')) /* Skip subdirs */
|
||||
{
|
||||
file++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Do the actual callback... */
|
||||
doEnumCallback(cb, callbackdata, origdir, dirNameEnd, strlen(dirNameEnd));
|
||||
|
||||
file++;
|
||||
}
|
||||
} /* LZMA_enumerateFiles */
|
||||
|
||||
|
||||
static int LZMA_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
return(lzma_find_file(archive, name) != NULL);
|
||||
} /* LZMA_exists */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
LZMAfile *file = lzma_find_file(archive, name);
|
||||
|
||||
*fileExists = (file != NULL);
|
||||
|
||||
BAIL_IF_MACRO(file == NULL, NULL, -1);
|
||||
BAIL_IF_MACRO(!file->item->IsLastWriteTimeDefined, NULL, -1); /* write-time may not be defined for every file */
|
||||
|
||||
return(lzma_filetime_to_unix_timestamp(&file->item->LastWriteTime));
|
||||
} /* LZMA_getLastModTime */
|
||||
|
||||
|
||||
static int LZMA_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
LZMAfile *file = lzma_find_file(archive, name);
|
||||
|
||||
*fileExists = (file != NULL);
|
||||
|
||||
return(file == NULL ? 0 : file->item->IsDirectory);
|
||||
} /* LZMA_isDirectory */
|
||||
|
||||
|
||||
static int LZMA_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* LZMA_isSymLink */
|
||||
|
||||
|
||||
static fvoid *LZMA_openRead(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
LZMAfile *file = lzma_find_file(archive, name);
|
||||
|
||||
*fileExists = (file != NULL);
|
||||
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, NULL);
|
||||
|
||||
file->position = 0;
|
||||
file->folder->references++; /* Increase refcount for automatic cleanup... */
|
||||
|
||||
return(file);
|
||||
} /* LZMA_openRead */
|
||||
|
||||
|
||||
static fvoid *LZMA_openWrite(dvoid *opaque, const char *filename)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* LZMA_openWrite */
|
||||
|
||||
|
||||
static fvoid *LZMA_openAppend(dvoid *opaque, const char *filename)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* LZMA_openAppend */
|
||||
|
||||
|
||||
static void LZMA_dirClose(dvoid *opaque)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
|
||||
|
||||
for (fileIndex = 0; fileIndex < numFiles; fileIndex++)
|
||||
{
|
||||
LZMA_fileClose(&archive->files[fileIndex]);
|
||||
} /* for */
|
||||
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
} /* LZMA_dirClose */
|
||||
|
||||
|
||||
static int LZMA_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* LZMA_remove */
|
||||
|
||||
|
||||
static int LZMA_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* LZMA_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_LZMA =
|
||||
{
|
||||
"7Z",
|
||||
LZMA_ARCHIVE_DESCRIPTION,
|
||||
"Dennis Schridde <devurandom@gmx.net>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_LZMA,
|
||||
LZMA_isArchive, /* isArchive() method */
|
||||
LZMA_openArchive, /* openArchive() method */
|
||||
LZMA_enumerateFiles, /* enumerateFiles() method */
|
||||
LZMA_exists, /* exists() method */
|
||||
LZMA_isDirectory, /* isDirectory() method */
|
||||
LZMA_isSymLink, /* isSymLink() method */
|
||||
LZMA_getLastModTime, /* getLastModTime() method */
|
||||
LZMA_openRead, /* openRead() method */
|
||||
LZMA_openWrite, /* openWrite() method */
|
||||
LZMA_openAppend, /* openAppend() method */
|
||||
LZMA_remove, /* remove() method */
|
||||
LZMA_mkdir, /* mkdir() method */
|
||||
LZMA_dirClose, /* dirClose() method */
|
||||
LZMA_read, /* read() method */
|
||||
LZMA_write, /* write() method */
|
||||
LZMA_eof, /* eof() method */
|
||||
LZMA_tell, /* tell() method */
|
||||
LZMA_seek, /* seek() method */
|
||||
LZMA_fileLength, /* fileLength() method */
|
||||
LZMA_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_7Z */
|
||||
|
||||
/* end of lzma.c ... */
|
||||
|
||||
471
project/jni/physfs/archivers/mvl.c
Normal file
471
project/jni/physfs/archivers/mvl.c
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* MVL support routines for PhysicsFS.
|
||||
*
|
||||
* This driver handles Descent II Movielib archives.
|
||||
*
|
||||
* The file format of MVL is quite easy...
|
||||
*
|
||||
* //MVL File format - Written by Heiko Herrmann
|
||||
* char sig[4] = {'D','M', 'V', 'L'}; // "DMVL"=Descent MoVie Library
|
||||
*
|
||||
* int num_files; // the number of files in this MVL
|
||||
*
|
||||
* struct {
|
||||
* char file_name[13]; // Filename, padded to 13 bytes with 0s
|
||||
* int file_size; // filesize in bytes
|
||||
* }DIR_STRUCT[num_files];
|
||||
*
|
||||
* struct {
|
||||
* char data[file_size]; // The file data
|
||||
* }FILE_STRUCT[num_files];
|
||||
*
|
||||
* (That info is from http://www.descent2.com/ddn/specs/mvl/)
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Bradley Bell.
|
||||
* Based on grp.c by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_MVL)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[13];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} MVLentry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
MVLentry *entries;
|
||||
} MVLinfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
MVLentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} MVLfileinfo;
|
||||
|
||||
|
||||
static void MVL_dirClose(dvoid *opaque)
|
||||
{
|
||||
MVLinfo *info = ((MVLinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* MVL_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
MVLentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* MVL_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* MVL_write */
|
||||
|
||||
|
||||
static int MVL_eof(fvoid *opaque)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
MVLentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* MVL_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_tell(fvoid *opaque)
|
||||
{
|
||||
return(((MVLfileinfo *) opaque)->curPos);
|
||||
} /* MVL_tell */
|
||||
|
||||
|
||||
static int MVL_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
MVLentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* MVL_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_fileLength(fvoid *opaque)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* MVL_fileLength */
|
||||
|
||||
|
||||
static int MVL_fileClose(fvoid *opaque)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* MVL_fileClose */
|
||||
|
||||
|
||||
static int mvl_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count)
|
||||
{
|
||||
PHYSFS_uint8 buf[4];
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
|
||||
goto openMvl_failed;
|
||||
|
||||
if (memcmp(buf, "DMVL", 4) != 0)
|
||||
{
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
goto openMvl_failed;
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openMvl_failed;
|
||||
|
||||
*count = PHYSFS_swapULE32(*count);
|
||||
|
||||
return(1);
|
||||
|
||||
openMvl_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* mvl_open */
|
||||
|
||||
|
||||
static int MVL_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount;
|
||||
int retval = mvl_open(filename, forWriting, &fh, &fileCount);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* MVL_isArchive */
|
||||
|
||||
|
||||
static int mvl_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const MVLentry *a = (const MVLentry *) _a;
|
||||
return(strcmp(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* mvl_entry_cmp */
|
||||
|
||||
|
||||
static void mvl_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
MVLentry tmp;
|
||||
MVLentry *first = &(((MVLentry *) _a)[one]);
|
||||
MVLentry *second = &(((MVLentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (MVLentry));
|
||||
memcpy(first, second, sizeof (MVLentry));
|
||||
memcpy(second, &tmp, sizeof (MVLentry));
|
||||
} /* if */
|
||||
} /* mvl_entry_swap */
|
||||
|
||||
|
||||
static int mvl_load_entries(const char *name, int forWriting, MVLinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
PHYSFS_uint32 location = 8; /* sizeof sig. */
|
||||
MVLentry *entry;
|
||||
|
||||
BAIL_IF_MACRO(!mvl_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (MVLentry *) allocator.Malloc(sizeof(MVLentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
location += (17 * fileCount);
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = location;
|
||||
location += entry->size;
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
mvl_entry_cmp, mvl_entry_swap);
|
||||
return(1);
|
||||
} /* mvl_load_entries */
|
||||
|
||||
|
||||
static void *MVL_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
MVLinfo *info = (MVLinfo *) allocator.Malloc(sizeof (MVLinfo));
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
memset(info, '\0', sizeof (MVLinfo));
|
||||
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, MVL_openArchive_failed);
|
||||
if (!mvl_load_entries(name, forWriting, info))
|
||||
goto MVL_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
return(info);
|
||||
|
||||
MVL_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* MVL_openArchive */
|
||||
|
||||
|
||||
static void MVL_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
/* no directories in MVL files. */
|
||||
if (*dname == '\0')
|
||||
{
|
||||
MVLinfo *info = ((MVLinfo *) opaque);
|
||||
MVLentry *entry = info->entries;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
cb(callbackdata, origdir, entry->name);
|
||||
} /* if */
|
||||
} /* MVL_enumerateFiles */
|
||||
|
||||
|
||||
static MVLentry *mvl_find_entry(MVLinfo *info, const char *name)
|
||||
{
|
||||
char *ptr = strchr(name, '.');
|
||||
MVLentry *a = info->entries;
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Rule out filenames to avoid unneeded processing...no dirs,
|
||||
* big filenames, or extensions > 3 chars.
|
||||
*/
|
||||
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
rc = __PHYSFS_stricmpASCII(name, a[middle].name);
|
||||
if (rc == 0) /* found it! */
|
||||
return(&a[middle]);
|
||||
else if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* mvl_find_entry */
|
||||
|
||||
|
||||
static int MVL_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
return(mvl_find_entry(((MVLinfo *) opaque), name) != NULL);
|
||||
} /* MVL_exists */
|
||||
|
||||
|
||||
static int MVL_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = MVL_exists(opaque, name);
|
||||
return(0); /* never directories in a groupfile. */
|
||||
} /* MVL_isDirectory */
|
||||
|
||||
|
||||
static int MVL_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = MVL_exists(opaque, name);
|
||||
return(0); /* never symlinks in a groupfile. */
|
||||
} /* MVL_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
MVLinfo *info = ((MVLinfo *) opaque);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
*fileExists = (mvl_find_entry(info, name) != NULL);
|
||||
if (*fileExists) /* use time of MVL itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* MVL_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *MVL_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
MVLinfo *info = ((MVLinfo *) opaque);
|
||||
MVLfileinfo *finfo;
|
||||
MVLentry *entry;
|
||||
|
||||
entry = mvl_find_entry(info, fnm);
|
||||
*fileExists = (entry != NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
||||
|
||||
finfo = (MVLfileinfo *) allocator.Malloc(sizeof (MVLfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* MVL_openRead */
|
||||
|
||||
|
||||
static fvoid *MVL_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* MVL_openWrite */
|
||||
|
||||
|
||||
static fvoid *MVL_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* MVL_openAppend */
|
||||
|
||||
|
||||
static int MVL_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* MVL_remove */
|
||||
|
||||
|
||||
static int MVL_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* MVL_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_MVL =
|
||||
{
|
||||
"MVL",
|
||||
MVL_ARCHIVE_DESCRIPTION,
|
||||
"Bradley Bell <btb@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_MVL,
|
||||
MVL_isArchive, /* isArchive() method */
|
||||
MVL_openArchive, /* openArchive() method */
|
||||
MVL_enumerateFiles, /* enumerateFiles() method */
|
||||
MVL_exists, /* exists() method */
|
||||
MVL_isDirectory, /* isDirectory() method */
|
||||
MVL_isSymLink, /* isSymLink() method */
|
||||
MVL_getLastModTime, /* getLastModTime() method */
|
||||
MVL_openRead, /* openRead() method */
|
||||
MVL_openWrite, /* openWrite() method */
|
||||
MVL_openAppend, /* openAppend() method */
|
||||
MVL_remove, /* remove() method */
|
||||
MVL_mkdir, /* mkdir() method */
|
||||
MVL_dirClose, /* dirClose() method */
|
||||
MVL_read, /* read() method */
|
||||
MVL_write, /* write() method */
|
||||
MVL_eof, /* eof() method */
|
||||
MVL_tell, /* tell() method */
|
||||
MVL_seek, /* seek() method */
|
||||
MVL_fileLength, /* fileLength() method */
|
||||
MVL_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_MVL */
|
||||
|
||||
/* end of mvl.c ... */
|
||||
|
||||
633
project/jni/physfs/archivers/qpak.c
Normal file
633
project/jni/physfs/archivers/qpak.c
Normal file
@@ -0,0 +1,633 @@
|
||||
/*
|
||||
* QPAK support routines for PhysicsFS.
|
||||
*
|
||||
* This archiver handles the archive format utilized by Quake 1 and 2.
|
||||
* Quake3-based games use the PkZip/Info-Zip format (which our zip.c
|
||||
* archiver handles).
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This format info (in more detail) comes from:
|
||||
* http://debian.fmi.uni-sofia.bg/~sergei/cgsr/docs/pak.txt
|
||||
*
|
||||
* Quake PAK Format
|
||||
*
|
||||
* Header
|
||||
* (4 bytes) signature = 'PACK'
|
||||
* (4 bytes) directory offset
|
||||
* (4 bytes) directory length
|
||||
*
|
||||
* Directory
|
||||
* (56 bytes) file name
|
||||
* (4 bytes) file position
|
||||
* (4 bytes) file length
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_QPAK)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
#if 1 /* Make this case insensitive? */
|
||||
#define QPAK_strcmp(x, y) __PHYSFS_stricmpASCII(x, y)
|
||||
#define QPAK_strncmp(x, y, z) __PHYSFS_strnicmpASCII(x, y, z)
|
||||
#else
|
||||
#define QPAK_strcmp(x, y) strcmp(x, y)
|
||||
#define QPAK_strncmp(x, y, z) strncmp(x, y, z)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[56];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} QPAKentry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
QPAKentry *entries;
|
||||
} QPAKinfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
QPAKentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} QPAKfileinfo;
|
||||
|
||||
/* Magic numbers... */
|
||||
#define QPAK_SIG 0x4b434150 /* "PACK" in ASCII. */
|
||||
|
||||
|
||||
static void QPAK_dirClose(dvoid *opaque)
|
||||
{
|
||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* QPAK_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
QPAKentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* QPAK_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* QPAK_write */
|
||||
|
||||
|
||||
static int QPAK_eof(fvoid *opaque)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
QPAKentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* QPAK_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_tell(fvoid *opaque)
|
||||
{
|
||||
return(((QPAKfileinfo *) opaque)->curPos);
|
||||
} /* QPAK_tell */
|
||||
|
||||
|
||||
static int QPAK_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
QPAKentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* QPAK_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_fileLength(fvoid *opaque)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* QPAK_fileLength */
|
||||
|
||||
|
||||
static int QPAK_fileClose(fvoid *opaque)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* QPAK_fileClose */
|
||||
|
||||
|
||||
static int qpak_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count)
|
||||
{
|
||||
PHYSFS_uint32 buf;
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openQpak_failed;
|
||||
|
||||
buf = PHYSFS_swapULE32(buf);
|
||||
GOTO_IF_MACRO(buf != QPAK_SIG, ERR_UNSUPPORTED_ARCHIVE, openQpak_failed);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openQpak_failed;
|
||||
|
||||
buf = PHYSFS_swapULE32(buf); /* directory table offset. */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openQpak_failed;
|
||||
|
||||
*count = PHYSFS_swapULE32(*count);
|
||||
|
||||
/* corrupted archive? */
|
||||
GOTO_IF_MACRO((*count % 64) != 0, ERR_CORRUPTED, openQpak_failed);
|
||||
|
||||
if (!__PHYSFS_platformSeek(*fh, buf))
|
||||
goto openQpak_failed;
|
||||
|
||||
*count /= 64;
|
||||
return(1);
|
||||
|
||||
openQpak_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* qpak_open */
|
||||
|
||||
|
||||
static int QPAK_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount;
|
||||
int retval = qpak_open(filename, forWriting, &fh, &fileCount);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* QPAK_isArchive */
|
||||
|
||||
|
||||
static int qpak_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const QPAKentry *a = (const QPAKentry *) _a;
|
||||
return(QPAK_strcmp(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* qpak_entry_cmp */
|
||||
|
||||
|
||||
static void qpak_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
QPAKentry tmp;
|
||||
QPAKentry *first = &(((QPAKentry *) _a)[one]);
|
||||
QPAKentry *second = &(((QPAKentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (QPAKentry));
|
||||
memcpy(first, second, sizeof (QPAKentry));
|
||||
memcpy(second, &tmp, sizeof (QPAKentry));
|
||||
} /* if */
|
||||
} /* qpak_entry_swap */
|
||||
|
||||
|
||||
static int qpak_load_entries(const char *name, int forWriting, QPAKinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
QPAKentry *entry;
|
||||
|
||||
BAIL_IF_MACRO(!qpak_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (QPAKentry*) allocator.Malloc(sizeof(QPAKentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
PHYSFS_uint32 loc;
|
||||
|
||||
if (__PHYSFS_platformRead(fh,&entry->name,sizeof(entry->name),1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh,&loc,sizeof(loc),1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh,&entry->size,sizeof(entry->size),1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = PHYSFS_swapULE32(loc);
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
qpak_entry_cmp, qpak_entry_swap);
|
||||
return(1);
|
||||
} /* qpak_load_entries */
|
||||
|
||||
|
||||
static void *QPAK_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
QPAKinfo *info = (QPAKinfo *) allocator.Malloc(sizeof (QPAKinfo));
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
memset(info, '\0', sizeof (QPAKinfo));
|
||||
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
if (info->filename == NULL)
|
||||
{
|
||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
||||
goto QPAK_openArchive_failed;
|
||||
} /* if */
|
||||
|
||||
if (!qpak_load_entries(name, forWriting, info))
|
||||
goto QPAK_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
return(info);
|
||||
|
||||
QPAK_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* QPAK_openArchive */
|
||||
|
||||
|
||||
static PHYSFS_sint32 qpak_find_start_of_dir(QPAKinfo *info, const char *path,
|
||||
int stop_on_first_find)
|
||||
{
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
PHYSFS_uint32 dlen = strlen(path);
|
||||
PHYSFS_sint32 retval = -1;
|
||||
const char *name;
|
||||
int rc;
|
||||
|
||||
if (*path == '\0') /* root dir? */
|
||||
return(0);
|
||||
|
||||
if ((dlen > 0) && (path[dlen - 1] == '/')) /* ignore trailing slash. */
|
||||
dlen--;
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
name = info->entries[middle].name;
|
||||
rc = QPAK_strncmp(path, name, dlen);
|
||||
if (rc == 0)
|
||||
{
|
||||
char ch = name[dlen];
|
||||
if (ch < '/') /* make sure this isn't just a substr match. */
|
||||
rc = -1;
|
||||
else if (ch > '/')
|
||||
rc = 1;
|
||||
else
|
||||
{
|
||||
if (stop_on_first_find) /* Just checking dir's existance? */
|
||||
return(middle);
|
||||
|
||||
if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
|
||||
return(middle + 1);
|
||||
|
||||
/* there might be more entries earlier in the list. */
|
||||
retval = middle;
|
||||
hi = middle - 1;
|
||||
} /* else */
|
||||
} /* if */
|
||||
|
||||
if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
return(retval);
|
||||
} /* qpak_find_start_of_dir */
|
||||
|
||||
|
||||
/*
|
||||
* Moved to seperate function so we can use alloca then immediately throw
|
||||
* away the allocated stack space...
|
||||
*/
|
||||
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
||||
const char *odir, const char *str, PHYSFS_sint32 ln)
|
||||
{
|
||||
char *newstr = __PHYSFS_smallAlloc(ln + 1);
|
||||
if (newstr == NULL)
|
||||
return;
|
||||
|
||||
memcpy(newstr, str, ln);
|
||||
newstr[ln] = '\0';
|
||||
cb(callbackdata, odir, newstr);
|
||||
__PHYSFS_smallFree(newstr);
|
||||
} /* doEnumCallback */
|
||||
|
||||
|
||||
static void QPAK_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
||||
PHYSFS_sint32 dlen, dlen_inc, max, i;
|
||||
|
||||
i = qpak_find_start_of_dir(info, dname, 0);
|
||||
if (i == -1) /* no such directory. */
|
||||
return;
|
||||
|
||||
dlen = strlen(dname);
|
||||
if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
|
||||
dlen--;
|
||||
|
||||
dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
|
||||
max = (PHYSFS_sint32) info->entryCount;
|
||||
while (i < max)
|
||||
{
|
||||
char *add;
|
||||
char *ptr;
|
||||
PHYSFS_sint32 ln;
|
||||
char *e = info->entries[i].name;
|
||||
if ((dlen) && ((QPAK_strncmp(e, dname, dlen)) || (e[dlen] != '/')))
|
||||
break; /* past end of this dir; we're done. */
|
||||
|
||||
add = e + dlen_inc;
|
||||
ptr = strchr(add, '/');
|
||||
ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
|
||||
doEnumCallback(cb, callbackdata, origdir, add, ln);
|
||||
ln += dlen_inc; /* point past entry to children... */
|
||||
|
||||
/* increment counter and skip children of subdirs... */
|
||||
while ((++i < max) && (ptr != NULL))
|
||||
{
|
||||
char *e_new = info->entries[i].name;
|
||||
if ((QPAK_strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))
|
||||
break;
|
||||
} /* while */
|
||||
} /* while */
|
||||
} /* QPAK_enumerateFiles */
|
||||
|
||||
|
||||
/*
|
||||
* This will find the QPAKentry associated with a path in platform-independent
|
||||
* notation. Directories don't have QPAKentries associated with them, but
|
||||
* (*isDir) will be set to non-zero if a dir was hit.
|
||||
*/
|
||||
static QPAKentry *qpak_find_entry(QPAKinfo *info, const char *path, int *isDir)
|
||||
{
|
||||
QPAKentry *a = info->entries;
|
||||
PHYSFS_sint32 pathlen = strlen(path);
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
const char *thispath = NULL;
|
||||
int rc;
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
thispath = a[middle].name;
|
||||
rc = QPAK_strncmp(path, thispath, pathlen);
|
||||
|
||||
if (rc > 0)
|
||||
lo = middle + 1;
|
||||
|
||||
else if (rc < 0)
|
||||
hi = middle - 1;
|
||||
|
||||
else /* substring match...might be dir or entry or nothing. */
|
||||
{
|
||||
if (isDir != NULL)
|
||||
{
|
||||
*isDir = (thispath[pathlen] == '/');
|
||||
if (*isDir)
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
if (thispath[pathlen] == '\0') /* found entry? */
|
||||
return(&a[middle]);
|
||||
/* adjust search params, try again. */
|
||||
else if (thispath[pathlen] > '/')
|
||||
hi = middle - 1;
|
||||
else
|
||||
lo = middle + 1;
|
||||
} /* if */
|
||||
} /* while */
|
||||
|
||||
if (isDir != NULL)
|
||||
*isDir = 0;
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* qpak_find_entry */
|
||||
|
||||
|
||||
static int QPAK_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
int isDir;
|
||||
QPAKinfo *info = (QPAKinfo *) opaque;
|
||||
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
|
||||
return((entry != NULL) || (isDir));
|
||||
} /* QPAK_exists */
|
||||
|
||||
|
||||
static int QPAK_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
QPAKinfo *info = (QPAKinfo *) opaque;
|
||||
int isDir;
|
||||
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
|
||||
|
||||
*fileExists = ((isDir) || (entry != NULL));
|
||||
if (isDir)
|
||||
return(1); /* definitely a dir. */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, 0);
|
||||
} /* QPAK_isDirectory */
|
||||
|
||||
|
||||
static int QPAK_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = QPAK_exists(opaque, name);
|
||||
return(0); /* never symlinks in a quake pak. */
|
||||
} /* QPAK_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
int isDir;
|
||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
|
||||
|
||||
*fileExists = ((isDir) || (entry != NULL));
|
||||
if (*fileExists) /* use time of QPAK itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* QPAK_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *QPAK_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
||||
QPAKfileinfo *finfo;
|
||||
QPAKentry *entry;
|
||||
int isDir;
|
||||
|
||||
entry = qpak_find_entry(info, fnm, &isDir);
|
||||
*fileExists = ((entry != NULL) || (isDir));
|
||||
BAIL_IF_MACRO(isDir, ERR_NOT_A_FILE, NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
finfo = (QPAKfileinfo *) allocator.Malloc(sizeof (QPAKfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* QPAK_openRead */
|
||||
|
||||
|
||||
static fvoid *QPAK_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* QPAK_openWrite */
|
||||
|
||||
|
||||
static fvoid *QPAK_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* QPAK_openAppend */
|
||||
|
||||
|
||||
static int QPAK_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* QPAK_remove */
|
||||
|
||||
|
||||
static int QPAK_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* QPAK_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_QPAK =
|
||||
{
|
||||
"PAK",
|
||||
QPAK_ARCHIVE_DESCRIPTION,
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_QPAK,
|
||||
QPAK_isArchive, /* isArchive() method */
|
||||
QPAK_openArchive, /* openArchive() method */
|
||||
QPAK_enumerateFiles, /* enumerateFiles() method */
|
||||
QPAK_exists, /* exists() method */
|
||||
QPAK_isDirectory, /* isDirectory() method */
|
||||
QPAK_isSymLink, /* isSymLink() method */
|
||||
QPAK_getLastModTime, /* getLastModTime() method */
|
||||
QPAK_openRead, /* openRead() method */
|
||||
QPAK_openWrite, /* openWrite() method */
|
||||
QPAK_openAppend, /* openAppend() method */
|
||||
QPAK_remove, /* remove() method */
|
||||
QPAK_mkdir, /* mkdir() method */
|
||||
QPAK_dirClose, /* dirClose() method */
|
||||
QPAK_read, /* read() method */
|
||||
QPAK_write, /* write() method */
|
||||
QPAK_eof, /* eof() method */
|
||||
QPAK_tell, /* tell() method */
|
||||
QPAK_seek, /* seek() method */
|
||||
QPAK_fileLength, /* fileLength() method */
|
||||
QPAK_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_QPAK */
|
||||
|
||||
/* end of qpak.c ... */
|
||||
|
||||
534
project/jni/physfs/archivers/wad.c
Normal file
534
project/jni/physfs/archivers/wad.c
Normal file
@@ -0,0 +1,534 @@
|
||||
/*
|
||||
* WAD support routines for PhysicsFS.
|
||||
*
|
||||
* This driver handles DOOM engine archives ("wads").
|
||||
* This format (but not this driver) was designed by id Software for use
|
||||
* with the DOOM engine.
|
||||
* The specs of the format are from the unofficial doom specs v1.666
|
||||
* found here: http://www.gamers.org/dhs/helpdocs/dmsp1666.html
|
||||
* The format of the archive: (from the specs)
|
||||
*
|
||||
* A WAD file has three parts:
|
||||
* (1) a twelve-byte header
|
||||
* (2) one or more "lumps"
|
||||
* (3) a directory or "info table" that contains the names, offsets, and
|
||||
* sizes of all the lumps in the WAD
|
||||
*
|
||||
* The header consists of three four-byte parts:
|
||||
* (a) an ASCII string which must be either "IWAD" or "PWAD"
|
||||
* (b) a 4-byte (long) integer which is the number of lumps in the wad
|
||||
* (c) a long integer which is the file offset to the start of
|
||||
* the directory
|
||||
*
|
||||
* The directory has one 16-byte entry for every lump. Each entry consists
|
||||
* of three parts:
|
||||
*
|
||||
* (a) a long integer, the file offset to the start of the lump
|
||||
* (b) a long integer, the size of the lump in bytes
|
||||
* (c) an 8-byte ASCII string, the name of the lump, padded with zeros.
|
||||
* For example, the "DEMO1" entry in hexadecimal would be
|
||||
* (44 45 4D 4F 31 00 00 00)
|
||||
*
|
||||
* Note that there is no way to tell if an opened WAD archive is a
|
||||
* IWAD or PWAD with this archiver.
|
||||
* I couldn't think of a way to provide that information, without being too
|
||||
* hacky.
|
||||
* I don't think it's really that important though.
|
||||
*
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Travis Wells, based on the GRP archiver by
|
||||
* Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_WAD)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[18];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} WADentry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
PHYSFS_uint32 entryOffset;
|
||||
WADentry *entries;
|
||||
} WADinfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
WADentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} WADfileinfo;
|
||||
|
||||
|
||||
static void WAD_dirClose(dvoid *opaque)
|
||||
{
|
||||
WADinfo *info = ((WADinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* WAD_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
WADentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* WAD_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* WAD_write */
|
||||
|
||||
|
||||
static int WAD_eof(fvoid *opaque)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
WADentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* WAD_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_tell(fvoid *opaque)
|
||||
{
|
||||
return(((WADfileinfo *) opaque)->curPos);
|
||||
} /* WAD_tell */
|
||||
|
||||
|
||||
static int WAD_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
WADentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* WAD_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_fileLength(fvoid *opaque)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* WAD_fileLength */
|
||||
|
||||
|
||||
static int WAD_fileClose(fvoid *opaque)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* WAD_fileClose */
|
||||
|
||||
|
||||
static int wad_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count,PHYSFS_uint32 *offset)
|
||||
{
|
||||
PHYSFS_uint8 buf[4];
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
|
||||
goto openWad_failed;
|
||||
|
||||
if (memcmp(buf, "IWAD", 4) != 0 && memcmp(buf, "PWAD", 4) != 0)
|
||||
{
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
goto openWad_failed;
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openWad_failed;
|
||||
|
||||
*count = PHYSFS_swapULE32(*count);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, offset, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openWad_failed;
|
||||
|
||||
*offset = PHYSFS_swapULE32(*offset);
|
||||
|
||||
return(1);
|
||||
|
||||
openWad_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* wad_open */
|
||||
|
||||
|
||||
static int WAD_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount,offset;
|
||||
int retval = wad_open(filename, forWriting, &fh, &fileCount,&offset);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* WAD_isArchive */
|
||||
|
||||
|
||||
static int wad_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const WADentry *a = (const WADentry *) _a;
|
||||
return(strcmp(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* wad_entry_cmp */
|
||||
|
||||
|
||||
static void wad_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
WADentry tmp;
|
||||
WADentry *first = &(((WADentry *) _a)[one]);
|
||||
WADentry *second = &(((WADentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (WADentry));
|
||||
memcpy(first, second, sizeof (WADentry));
|
||||
memcpy(second, &tmp, sizeof (WADentry));
|
||||
} /* if */
|
||||
} /* wad_entry_swap */
|
||||
|
||||
|
||||
static int wad_load_entries(const char *name, int forWriting, WADinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
PHYSFS_uint32 directoryOffset;
|
||||
WADentry *entry;
|
||||
char lastDirectory[9];
|
||||
|
||||
lastDirectory[8] = 0; /* Make sure lastDirectory stays null-terminated. */
|
||||
|
||||
BAIL_IF_MACRO(!wad_open(name, forWriting, &fh, &fileCount,&directoryOffset), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (WADentry *) allocator.Malloc(sizeof(WADentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
__PHYSFS_platformSeek(fh,directoryOffset);
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
if (__PHYSFS_platformRead(fh, &entry->startPos, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->name, 8, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->name[8] = '\0'; /* name might not be null-terminated in file. */
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = PHYSFS_swapULE32(entry->startPos);
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
wad_entry_cmp, wad_entry_swap);
|
||||
return(1);
|
||||
} /* wad_load_entries */
|
||||
|
||||
|
||||
static void *WAD_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
WADinfo *info = (WADinfo *) allocator.Malloc(sizeof (WADinfo));
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
memset(info, '\0', sizeof (WADinfo));
|
||||
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, WAD_openArchive_failed);
|
||||
|
||||
if (!wad_load_entries(name, forWriting, info))
|
||||
goto WAD_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
return(info);
|
||||
|
||||
WAD_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* WAD_openArchive */
|
||||
|
||||
|
||||
static void WAD_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
WADinfo *info = ((WADinfo *) opaque);
|
||||
WADentry *entry = info->entries;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
const char *name;
|
||||
char *sep;
|
||||
|
||||
if (*dname == '\0') /* root directory enumeration? */
|
||||
{
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
{
|
||||
name = entry->name;
|
||||
if (strchr(name, '/') == NULL)
|
||||
cb(callbackdata, origdir, name);
|
||||
} /* for */
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
{
|
||||
name = entry->name;
|
||||
sep = strchr(name, '/');
|
||||
if (sep != NULL)
|
||||
{
|
||||
if (strncmp(dname, name, (sep - name)) == 0)
|
||||
cb(callbackdata, origdir, sep + 1);
|
||||
} /* if */
|
||||
} /* for */
|
||||
} /* else */
|
||||
} /* WAD_enumerateFiles */
|
||||
|
||||
|
||||
static WADentry *wad_find_entry(WADinfo *info, const char *name)
|
||||
{
|
||||
WADentry *a = info->entries;
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
int rc;
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
rc = strcmp(name, a[middle].name);
|
||||
if (rc == 0) /* found it! */
|
||||
return(&a[middle]);
|
||||
else if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* wad_find_entry */
|
||||
|
||||
|
||||
static int WAD_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
return(wad_find_entry(((WADinfo *) opaque), name) != NULL);
|
||||
} /* WAD_exists */
|
||||
|
||||
|
||||
static int WAD_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
WADentry *entry = wad_find_entry(((WADinfo *) opaque), name);
|
||||
if (entry != NULL)
|
||||
{
|
||||
char *n;
|
||||
|
||||
*fileExists = 1;
|
||||
|
||||
/* Can't be a directory if it's a subdirectory. */
|
||||
if (strchr(entry->name, '/') != NULL)
|
||||
return(0);
|
||||
|
||||
/* Check if it matches "MAP??" or "E?M?" ... */
|
||||
n = entry->name;
|
||||
if ((n[0] == 'E' && n[2] == 'M') ||
|
||||
(n[0] == 'M' && n[1] == 'A' && n[2] == 'P' && n[6] == 0))
|
||||
{
|
||||
return(1);
|
||||
} /* if */
|
||||
return(0);
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
*fileExists = 0;
|
||||
return(0);
|
||||
} /* else */
|
||||
} /* WAD_isDirectory */
|
||||
|
||||
|
||||
static int WAD_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = WAD_exists(opaque, name);
|
||||
return(0); /* never symlinks in a wad. */
|
||||
} /* WAD_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
WADinfo *info = ((WADinfo *) opaque);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
*fileExists = (wad_find_entry(info, name) != NULL);
|
||||
if (*fileExists) /* use time of WAD itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* WAD_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *WAD_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
WADinfo *info = ((WADinfo *) opaque);
|
||||
WADfileinfo *finfo;
|
||||
WADentry *entry;
|
||||
|
||||
entry = wad_find_entry(info, fnm);
|
||||
*fileExists = (entry != NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
||||
|
||||
finfo = (WADfileinfo *) allocator.Malloc(sizeof (WADfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* WAD_openRead */
|
||||
|
||||
|
||||
static fvoid *WAD_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* WAD_openWrite */
|
||||
|
||||
|
||||
static fvoid *WAD_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* WAD_openAppend */
|
||||
|
||||
|
||||
static int WAD_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* WAD_remove */
|
||||
|
||||
|
||||
static int WAD_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* WAD_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_WAD =
|
||||
{
|
||||
"WAD",
|
||||
WAD_ARCHIVE_DESCRIPTION,
|
||||
"Travis Wells <traviswells@mchsi.com>",
|
||||
"http://www.3dmm2.com/doom/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_WAD,
|
||||
WAD_isArchive, /* isArchive() method */
|
||||
WAD_openArchive, /* openArchive() method */
|
||||
WAD_enumerateFiles, /* enumerateFiles() method */
|
||||
WAD_exists, /* exists() method */
|
||||
WAD_isDirectory, /* isDirectory() method */
|
||||
WAD_isSymLink, /* isSymLink() method */
|
||||
WAD_getLastModTime, /* getLastModTime() method */
|
||||
WAD_openRead, /* openRead() method */
|
||||
WAD_openWrite, /* openWrite() method */
|
||||
WAD_openAppend, /* openAppend() method */
|
||||
WAD_remove, /* remove() method */
|
||||
WAD_mkdir, /* mkdir() method */
|
||||
WAD_dirClose, /* dirClose() method */
|
||||
WAD_read, /* read() method */
|
||||
WAD_write, /* write() method */
|
||||
WAD_eof, /* eof() method */
|
||||
WAD_tell, /* tell() method */
|
||||
WAD_seek, /* seek() method */
|
||||
WAD_fileLength, /* fileLength() method */
|
||||
WAD_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_WAD */
|
||||
|
||||
/* end of wad.c ... */
|
||||
|
||||
1454
project/jni/physfs/archivers/zip.c
Normal file
1454
project/jni/physfs/archivers/zip.c
Normal file
File diff suppressed because it is too large
Load Diff
2395
project/jni/physfs/include/physfs.h
Normal file
2395
project/jni/physfs/include/physfs.h
Normal file
File diff suppressed because it is too large
Load Diff
2013
project/jni/physfs/include/physfs_casefolding.h
Normal file
2013
project/jni/physfs/include/physfs_casefolding.h
Normal file
File diff suppressed because it is too large
Load Diff
1496
project/jni/physfs/include/physfs_internal.h
Normal file
1496
project/jni/physfs/include/physfs_internal.h
Normal file
File diff suppressed because it is too large
Load Diff
49
project/jni/physfs/include/physfs_platforms.h
Normal file
49
project/jni/physfs/include/physfs_platforms.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef _INCL_PHYSFS_PLATFORMS
|
||||
#define _INCL_PHYSFS_PLATFORMS
|
||||
|
||||
#ifndef __PHYSICSFS_INTERNAL__
|
||||
#error Do not include this header from your applications.
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These only define the platforms to determine which files in the platforms
|
||||
* directory should be compiled. For example, technically BeOS can be called
|
||||
* a "unix" system, but since it doesn't use unix.c, we don't define
|
||||
* PHYSFS_PLATFORM_UNIX on that system.
|
||||
*/
|
||||
|
||||
#if (defined __HAIKU__)
|
||||
# define PHYSFS_PLATFORM_HAIKU
|
||||
# define PHYSFS_PLATFORM_BEOS
|
||||
# define PHYSFS_PLATFORM_POSIX
|
||||
#elif ((defined __BEOS__) || (defined __beos__))
|
||||
# define PHYSFS_PLATFORM_BEOS
|
||||
# define PHYSFS_PLATFORM_POSIX
|
||||
#elif (defined _WIN32_WCE) || (defined _WIN64_WCE)
|
||||
# define PHYSFS_PLATFORM_POCKETPC
|
||||
#elif (((defined _WIN32) || (defined _WIN64)) && (!defined __CYGWIN__))
|
||||
# define PHYSFS_PLATFORM_WINDOWS
|
||||
#elif (defined OS2)
|
||||
# define PHYSFS_PLATFORM_OS2
|
||||
#elif ((defined __MACH__) && (defined __APPLE__))
|
||||
/* To check if iphone or not, we need to include this file */
|
||||
# include <TargetConditionals.h>
|
||||
# if ((TARGET_IPHONE_SIMULATOR) || (TARGET_OS_IPHONE))
|
||||
# define PHYSFS_PLATFORM_UNIX
|
||||
# define PHYSFS_PLATFORM_POSIX
|
||||
# define PHYSFS_NO_CDROM_SUPPORT
|
||||
# else
|
||||
# define PHYSFS_PLATFORM_MACOSX
|
||||
# define PHYSFS_PLATFORM_POSIX
|
||||
# endif
|
||||
#elif defined(macintosh)
|
||||
# error Classic Mac OS support was dropped from PhysicsFS 2.0. Move to OS X.
|
||||
#elif defined(unix)
|
||||
# define PHYSFS_PLATFORM_UNIX
|
||||
# define PHYSFS_PLATFORM_POSIX
|
||||
#else
|
||||
# error Unknown platform.
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker. */
|
||||
|
||||
2221
project/jni/physfs/physfs.c
Normal file
2221
project/jni/physfs/physfs.c
Normal file
File diff suppressed because it is too large
Load Diff
312
project/jni/physfs/physfs_byteorder.c
Normal file
312
project/jni/physfs/physfs_byteorder.c
Normal file
@@ -0,0 +1,312 @@
|
||||
/**
|
||||
* PhysicsFS; a portable, flexible file i/o abstraction.
|
||||
*
|
||||
* Documentation is in physfs.h. It's verbose, honest. :)
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
#if (defined macintosh) && !(defined __MWERKS__)
|
||||
#define __inline__
|
||||
#endif
|
||||
|
||||
#if (defined _MSC_VER)
|
||||
#define __inline__ __inline
|
||||
#endif
|
||||
|
||||
#ifndef PHYSFS_Swap16
|
||||
static __inline__ PHYSFS_uint16 PHYSFS_Swap16(PHYSFS_uint16 D)
|
||||
{
|
||||
return((D<<8)|(D>>8));
|
||||
}
|
||||
#endif
|
||||
#ifndef PHYSFS_Swap32
|
||||
static __inline__ PHYSFS_uint32 PHYSFS_Swap32(PHYSFS_uint32 D)
|
||||
{
|
||||
return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24));
|
||||
}
|
||||
#endif
|
||||
#ifndef PHYSFS_NO_64BIT_SUPPORT
|
||||
#ifndef PHYSFS_Swap64
|
||||
static __inline__ PHYSFS_uint64 PHYSFS_Swap64(PHYSFS_uint64 val) {
|
||||
PHYSFS_uint32 hi, lo;
|
||||
|
||||
/* Separate into high and low 32-bit values and swap them */
|
||||
lo = (PHYSFS_uint32)(val&0xFFFFFFFF);
|
||||
val >>= 32;
|
||||
hi = (PHYSFS_uint32)(val&0xFFFFFFFF);
|
||||
val = PHYSFS_Swap32(lo);
|
||||
val <<= 32;
|
||||
val |= PHYSFS_Swap32(hi);
|
||||
return(val);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#ifndef PHYSFS_Swap64
|
||||
/* This is mainly to keep compilers from complaining in PHYSFS code.
|
||||
If there is no real 64-bit datatype, then compilers will complain about
|
||||
the fake 64-bit datatype that PHYSFS provides when it compiles user code.
|
||||
*/
|
||||
#define PHYSFS_Swap64(X) (X)
|
||||
#endif
|
||||
#endif /* PHYSFS_NO_64BIT_SUPPORT */
|
||||
|
||||
|
||||
/* Byteswap item from the specified endianness to the native endianness */
|
||||
#if PHYSFS_BYTEORDER == PHYSFS_LIL_ENDIAN
|
||||
PHYSFS_uint16 PHYSFS_swapULE16(PHYSFS_uint16 x) { return(x); }
|
||||
PHYSFS_sint16 PHYSFS_swapSLE16(PHYSFS_sint16 x) { return(x); }
|
||||
PHYSFS_uint32 PHYSFS_swapULE32(PHYSFS_uint32 x) { return(x); }
|
||||
PHYSFS_sint32 PHYSFS_swapSLE32(PHYSFS_sint32 x) { return(x); }
|
||||
PHYSFS_uint64 PHYSFS_swapULE64(PHYSFS_uint64 x) { return(x); }
|
||||
PHYSFS_sint64 PHYSFS_swapSLE64(PHYSFS_sint64 x) { return(x); }
|
||||
|
||||
PHYSFS_uint16 PHYSFS_swapUBE16(PHYSFS_uint16 x) { return(PHYSFS_Swap16(x)); }
|
||||
PHYSFS_sint16 PHYSFS_swapSBE16(PHYSFS_sint16 x) { return(PHYSFS_Swap16(x)); }
|
||||
PHYSFS_uint32 PHYSFS_swapUBE32(PHYSFS_uint32 x) { return(PHYSFS_Swap32(x)); }
|
||||
PHYSFS_sint32 PHYSFS_swapSBE32(PHYSFS_sint32 x) { return(PHYSFS_Swap32(x)); }
|
||||
PHYSFS_uint64 PHYSFS_swapUBE64(PHYSFS_uint64 x) { return(PHYSFS_Swap64(x)); }
|
||||
PHYSFS_sint64 PHYSFS_swapSBE64(PHYSFS_sint64 x) { return(PHYSFS_Swap64(x)); }
|
||||
#else
|
||||
PHYSFS_uint16 PHYSFS_swapULE16(PHYSFS_uint16 x) { return(PHYSFS_Swap16(x)); }
|
||||
PHYSFS_sint16 PHYSFS_swapSLE16(PHYSFS_sint16 x) { return(PHYSFS_Swap16(x)); }
|
||||
PHYSFS_uint32 PHYSFS_swapULE32(PHYSFS_uint32 x) { return(PHYSFS_Swap32(x)); }
|
||||
PHYSFS_sint32 PHYSFS_swapSLE32(PHYSFS_sint32 x) { return(PHYSFS_Swap32(x)); }
|
||||
PHYSFS_uint64 PHYSFS_swapULE64(PHYSFS_uint64 x) { return(PHYSFS_Swap64(x)); }
|
||||
PHYSFS_sint64 PHYSFS_swapSLE64(PHYSFS_sint64 x) { return(PHYSFS_Swap64(x)); }
|
||||
|
||||
PHYSFS_uint16 PHYSFS_swapUBE16(PHYSFS_uint16 x) { return(x); }
|
||||
PHYSFS_sint16 PHYSFS_swapSBE16(PHYSFS_sint16 x) { return(x); }
|
||||
PHYSFS_uint32 PHYSFS_swapUBE32(PHYSFS_uint32 x) { return(x); }
|
||||
PHYSFS_sint32 PHYSFS_swapSBE32(PHYSFS_sint32 x) { return(x); }
|
||||
PHYSFS_uint64 PHYSFS_swapUBE64(PHYSFS_uint64 x) { return(x); }
|
||||
PHYSFS_sint64 PHYSFS_swapSBE64(PHYSFS_sint64 x) { return(x); }
|
||||
#endif
|
||||
|
||||
|
||||
int PHYSFS_readSLE16(PHYSFS_File *file, PHYSFS_sint16 *val)
|
||||
{
|
||||
PHYSFS_sint16 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapSLE16(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readSLE16 */
|
||||
|
||||
|
||||
int PHYSFS_readULE16(PHYSFS_File *file, PHYSFS_uint16 *val)
|
||||
{
|
||||
PHYSFS_uint16 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapULE16(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readULE16 */
|
||||
|
||||
|
||||
int PHYSFS_readSBE16(PHYSFS_File *file, PHYSFS_sint16 *val)
|
||||
{
|
||||
PHYSFS_sint16 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapSBE16(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readSBE16 */
|
||||
|
||||
|
||||
int PHYSFS_readUBE16(PHYSFS_File *file, PHYSFS_uint16 *val)
|
||||
{
|
||||
PHYSFS_uint16 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapUBE16(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readUBE16 */
|
||||
|
||||
|
||||
int PHYSFS_readSLE32(PHYSFS_File *file, PHYSFS_sint32 *val)
|
||||
{
|
||||
PHYSFS_sint32 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapSLE32(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readSLE32 */
|
||||
|
||||
|
||||
int PHYSFS_readULE32(PHYSFS_File *file, PHYSFS_uint32 *val)
|
||||
{
|
||||
PHYSFS_uint32 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapULE32(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readULE32 */
|
||||
|
||||
|
||||
int PHYSFS_readSBE32(PHYSFS_File *file, PHYSFS_sint32 *val)
|
||||
{
|
||||
PHYSFS_sint32 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapSBE32(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readSBE32 */
|
||||
|
||||
|
||||
int PHYSFS_readUBE32(PHYSFS_File *file, PHYSFS_uint32 *val)
|
||||
{
|
||||
PHYSFS_uint32 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapUBE32(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readUBE32 */
|
||||
|
||||
|
||||
int PHYSFS_readSLE64(PHYSFS_File *file, PHYSFS_sint64 *val)
|
||||
{
|
||||
PHYSFS_sint64 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapSLE64(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readSLE64 */
|
||||
|
||||
|
||||
int PHYSFS_readULE64(PHYSFS_File *file, PHYSFS_uint64 *val)
|
||||
{
|
||||
PHYSFS_uint64 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapULE64(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readULE64 */
|
||||
|
||||
|
||||
int PHYSFS_readSBE64(PHYSFS_File *file, PHYSFS_sint64 *val)
|
||||
{
|
||||
PHYSFS_sint64 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapSBE64(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readSBE64 */
|
||||
|
||||
|
||||
int PHYSFS_readUBE64(PHYSFS_File *file, PHYSFS_uint64 *val)
|
||||
{
|
||||
PHYSFS_uint64 in;
|
||||
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
|
||||
*val = PHYSFS_swapUBE64(in);
|
||||
return(1);
|
||||
} /* PHYSFS_readUBE64 */
|
||||
|
||||
|
||||
|
||||
int PHYSFS_writeSLE16(PHYSFS_File *file, PHYSFS_sint16 val)
|
||||
{
|
||||
PHYSFS_sint16 out = PHYSFS_swapSLE16(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeSLE16 */
|
||||
|
||||
|
||||
int PHYSFS_writeULE16(PHYSFS_File *file, PHYSFS_uint16 val)
|
||||
{
|
||||
PHYSFS_uint16 out = PHYSFS_swapULE16(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeULE16 */
|
||||
|
||||
|
||||
int PHYSFS_writeSBE16(PHYSFS_File *file, PHYSFS_sint16 val)
|
||||
{
|
||||
PHYSFS_sint16 out = PHYSFS_swapSBE16(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeSBE16 */
|
||||
|
||||
|
||||
int PHYSFS_writeUBE16(PHYSFS_File *file, PHYSFS_uint16 val)
|
||||
{
|
||||
PHYSFS_uint16 out = PHYSFS_swapUBE16(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeUBE16 */
|
||||
|
||||
|
||||
int PHYSFS_writeSLE32(PHYSFS_File *file, PHYSFS_sint32 val)
|
||||
{
|
||||
PHYSFS_sint32 out = PHYSFS_swapSLE32(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeSLE32 */
|
||||
|
||||
|
||||
int PHYSFS_writeULE32(PHYSFS_File *file, PHYSFS_uint32 val)
|
||||
{
|
||||
PHYSFS_uint32 out = PHYSFS_swapULE32(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeULE32 */
|
||||
|
||||
|
||||
int PHYSFS_writeSBE32(PHYSFS_File *file, PHYSFS_sint32 val)
|
||||
{
|
||||
PHYSFS_sint32 out = PHYSFS_swapSBE32(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeSBE32 */
|
||||
|
||||
|
||||
int PHYSFS_writeUBE32(PHYSFS_File *file, PHYSFS_uint32 val)
|
||||
{
|
||||
PHYSFS_uint32 out = PHYSFS_swapUBE32(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeUBE32 */
|
||||
|
||||
|
||||
int PHYSFS_writeSLE64(PHYSFS_File *file, PHYSFS_sint64 val)
|
||||
{
|
||||
PHYSFS_sint64 out = PHYSFS_swapSLE64(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeSLE64 */
|
||||
|
||||
|
||||
int PHYSFS_writeULE64(PHYSFS_File *file, PHYSFS_uint64 val)
|
||||
{
|
||||
PHYSFS_uint64 out = PHYSFS_swapULE64(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeULE64 */
|
||||
|
||||
|
||||
int PHYSFS_writeSBE64(PHYSFS_File *file, PHYSFS_sint64 val)
|
||||
{
|
||||
PHYSFS_sint64 out = PHYSFS_swapSBE64(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeSBE64 */
|
||||
|
||||
|
||||
int PHYSFS_writeUBE64(PHYSFS_File *file, PHYSFS_uint64 val)
|
||||
{
|
||||
PHYSFS_uint64 out = PHYSFS_swapUBE64(val);
|
||||
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
|
||||
return(1);
|
||||
} /* PHYSFS_writeUBE64 */
|
||||
|
||||
/* end of physfs_byteorder.c ... */
|
||||
|
||||
460
project/jni/physfs/physfs_unicode.c
Normal file
460
project/jni/physfs/physfs_unicode.c
Normal file
@@ -0,0 +1,460 @@
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
|
||||
/*
|
||||
* From rfc3629, the UTF-8 spec:
|
||||
* http://www.ietf.org/rfc/rfc3629.txt
|
||||
*
|
||||
* Char. number range | UTF-8 octet sequence
|
||||
* (hexadecimal) | (binary)
|
||||
* --------------------+---------------------------------------------
|
||||
* 0000 0000-0000 007F | 0xxxxxxx
|
||||
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF
|
||||
|
||||
/*
|
||||
* This is the codepoint we currently return when there was bogus bits in a
|
||||
* UTF-8 string. May not fly in Asian locales?
|
||||
*/
|
||||
#define UNICODE_BOGUS_CHAR_CODEPOINT '?'
|
||||
|
||||
static PHYSFS_uint32 utf8codepoint(const char **_str)
|
||||
{
|
||||
const char *str = *_str;
|
||||
PHYSFS_uint32 retval = 0;
|
||||
PHYSFS_uint32 octet = (PHYSFS_uint32) ((PHYSFS_uint8) *str);
|
||||
PHYSFS_uint32 octet2, octet3, octet4;
|
||||
|
||||
if (octet == 0) /* null terminator, end of string. */
|
||||
return 0;
|
||||
|
||||
else if (octet < 128) /* one octet char: 0 to 127 */
|
||||
{
|
||||
(*_str)++; /* skip to next possible start of codepoint. */
|
||||
return(octet);
|
||||
} /* else if */
|
||||
|
||||
else if ((octet > 127) && (octet < 192)) /* bad (starts with 10xxxxxx). */
|
||||
{
|
||||
/*
|
||||
* Apparently each of these is supposed to be flagged as a bogus
|
||||
* char, instead of just resyncing to the next valid codepoint.
|
||||
*/
|
||||
(*_str)++; /* skip to next possible start of codepoint. */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* else if */
|
||||
|
||||
else if (octet < 224) /* two octets */
|
||||
{
|
||||
octet -= (128+64);
|
||||
octet2 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 2; /* skip to next possible start of codepoint. */
|
||||
retval = ((octet << 6) | (octet2 - 128));
|
||||
if ((retval >= 0x80) && (retval <= 0x7FF))
|
||||
return retval;
|
||||
} /* else if */
|
||||
|
||||
else if (octet < 240) /* three octets */
|
||||
{
|
||||
octet -= (128+64+32);
|
||||
octet2 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet3 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 3; /* skip to next possible start of codepoint. */
|
||||
retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) );
|
||||
|
||||
/* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */
|
||||
switch (retval)
|
||||
{
|
||||
case 0xD800:
|
||||
case 0xDB7F:
|
||||
case 0xDB80:
|
||||
case 0xDBFF:
|
||||
case 0xDC00:
|
||||
case 0xDF80:
|
||||
case 0xDFFF:
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* switch */
|
||||
|
||||
/* 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. */
|
||||
if ((retval >= 0x800) && (retval <= 0xFFFD))
|
||||
return retval;
|
||||
} /* else if */
|
||||
|
||||
else if (octet < 248) /* four octets */
|
||||
{
|
||||
octet -= (128+64+32+16);
|
||||
octet2 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet3 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet4 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet4 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 4; /* skip to next possible start of codepoint. */
|
||||
retval = ( ((octet << 18)) | ((octet2 - 128) << 12) |
|
||||
((octet3 - 128) << 6) | ((octet4 - 128)) );
|
||||
if ((retval >= 0x10000) && (retval <= 0x10FFFF))
|
||||
return retval;
|
||||
} /* else if */
|
||||
|
||||
/*
|
||||
* Five and six octet sequences became illegal in rfc3629.
|
||||
* We throw the codepoint away, but parse them to make sure we move
|
||||
* ahead the right number of bytes and don't overflow the buffer.
|
||||
*/
|
||||
|
||||
else if (octet < 252) /* five octets */
|
||||
{
|
||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 5; /* skip to next possible start of codepoint. */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* else if */
|
||||
|
||||
else /* six octets */
|
||||
{
|
||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
|
||||
*_str += 6; /* skip to next possible start of codepoint. */
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* else if */
|
||||
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* utf8codepoint */
|
||||
|
||||
|
||||
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);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
*(dst++) = cp;
|
||||
len -= sizeof (PHYSFS_uint32);
|
||||
} /* while */
|
||||
|
||||
*dst = 0;
|
||||
} /* PHYSFS_utf8ToUcs4 */
|
||||
|
||||
|
||||
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);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
|
||||
/* !!! BLUESKY: UTF-16 surrogates? */
|
||||
if (cp > 0xFFFF)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
|
||||
*(dst++) = cp;
|
||||
len -= sizeof (PHYSFS_uint16);
|
||||
} /* while */
|
||||
|
||||
*dst = 0;
|
||||
} /* PHYSFS_utf8ToUcs2 */
|
||||
|
||||
static void utf8fromcodepoint(PHYSFS_uint32 cp, char **_dst, PHYSFS_uint64 *_len)
|
||||
{
|
||||
char *dst = *_dst;
|
||||
PHYSFS_uint64 len = *_len;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (cp > 0x10FFFF)
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
else if ((cp == 0xFFFE) || (cp == 0xFFFF)) /* illegal values. */
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
else
|
||||
{
|
||||
/* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */
|
||||
switch (cp)
|
||||
{
|
||||
case 0xD800:
|
||||
case 0xDB7F:
|
||||
case 0xDB80:
|
||||
case 0xDBFF:
|
||||
case 0xDC00:
|
||||
case 0xDF80:
|
||||
case 0xDFFF:
|
||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
||||
} /* switch */
|
||||
} /* else */
|
||||
|
||||
/* Do the encoding... */
|
||||
if (cp < 0x80)
|
||||
{
|
||||
*(dst++) = (char) cp;
|
||||
len--;
|
||||
} /* if */
|
||||
|
||||
else if (cp < 0x800)
|
||||
{
|
||||
if (len < 2)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
*(dst++) = (char) ((cp >> 6) | 128 | 64);
|
||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
||||
len -= 2;
|
||||
} /* else */
|
||||
} /* else if */
|
||||
|
||||
else if (cp < 0x10000)
|
||||
{
|
||||
if (len < 3)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
*(dst++) = (char) ((cp >> 12) | 128 | 64 | 32);
|
||||
*(dst++) = (char) ((cp >> 6) & 0x3F) | 128;
|
||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
||||
len -= 3;
|
||||
} /* else */
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
if (len < 4)
|
||||
len = 0;
|
||||
else
|
||||
{
|
||||
*(dst++) = (char) ((cp >> 18) | 128 | 64 | 32 | 16);
|
||||
*(dst++) = (char) ((cp >> 12) & 0x3F) | 128;
|
||||
*(dst++) = (char) ((cp >> 6) & 0x3F) | 128;
|
||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
||||
len -= 4;
|
||||
} /* else if */
|
||||
} /* else */
|
||||
|
||||
*_dst = dst;
|
||||
*_len = len;
|
||||
} /* utf8fromcodepoint */
|
||||
|
||||
#define UTF8FROMTYPE(typ, src, dst, len) \
|
||||
if (len == 0) return; \
|
||||
len--; \
|
||||
while (len) \
|
||||
{ \
|
||||
const PHYSFS_uint32 cp = (PHYSFS_uint32) ((typ) (*(src++))); \
|
||||
if (cp == 0) break; \
|
||||
utf8fromcodepoint(cp, &dst, &len); \
|
||||
} \
|
||||
*dst = '\0'; \
|
||||
|
||||
void PHYSFS_utf8FromUcs4(const PHYSFS_uint32 *src, char *dst, PHYSFS_uint64 len)
|
||||
{
|
||||
UTF8FROMTYPE(PHYSFS_uint32, src, dst, len);
|
||||
} /* PHYSFS_utf8FromUcs4 */
|
||||
|
||||
void PHYSFS_utf8FromUcs2(const PHYSFS_uint16 *src, char *dst, PHYSFS_uint64 len)
|
||||
{
|
||||
UTF8FROMTYPE(PHYSFS_uint64, src, dst, len);
|
||||
} /* PHYSFS_utf8FromUcs4 */
|
||||
|
||||
/* latin1 maps to unicode codepoints directly, we just utf-8 encode it. */
|
||||
void PHYSFS_utf8FromLatin1(const char *src, char *dst, PHYSFS_uint64 len)
|
||||
{
|
||||
UTF8FROMTYPE(PHYSFS_uint8, src, dst, len);
|
||||
} /* PHYSFS_utf8FromLatin1 */
|
||||
|
||||
#undef UTF8FROMTYPE
|
||||
|
||||
|
||||
typedef struct CaseFoldMapping
|
||||
{
|
||||
PHYSFS_uint32 from;
|
||||
PHYSFS_uint32 to0;
|
||||
PHYSFS_uint32 to1;
|
||||
PHYSFS_uint32 to2;
|
||||
} CaseFoldMapping;
|
||||
|
||||
typedef struct CaseFoldHashBucket
|
||||
{
|
||||
const PHYSFS_uint8 count;
|
||||
const CaseFoldMapping *list;
|
||||
} CaseFoldHashBucket;
|
||||
|
||||
#include "physfs_casefolding.h"
|
||||
|
||||
static void locate_case_fold_mapping(const PHYSFS_uint32 from,
|
||||
PHYSFS_uint32 *to)
|
||||
{
|
||||
PHYSFS_uint32 i;
|
||||
const PHYSFS_uint8 hashed = ((from ^ (from >> 8)) & 0xFF);
|
||||
const CaseFoldHashBucket *bucket = &case_fold_hash[hashed];
|
||||
const CaseFoldMapping *mapping = bucket->list;
|
||||
|
||||
for (i = 0; i < bucket->count; i++, mapping++)
|
||||
{
|
||||
if (mapping->from == from)
|
||||
{
|
||||
to[0] = mapping->to0;
|
||||
to[1] = mapping->to1;
|
||||
to[2] = mapping->to2;
|
||||
return;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
/* Not found...there's no remapping for this codepoint. */
|
||||
to[0] = from;
|
||||
to[1] = 0;
|
||||
to[2] = 0;
|
||||
} /* locate_case_fold_mapping */
|
||||
|
||||
|
||||
static int utf8codepointcmp(const PHYSFS_uint32 cp1, const PHYSFS_uint32 cp2)
|
||||
{
|
||||
PHYSFS_uint32 folded1[3], folded2[3];
|
||||
locate_case_fold_mapping(cp1, folded1);
|
||||
locate_case_fold_mapping(cp2, folded2);
|
||||
return ( (folded1[0] == folded2[0]) &&
|
||||
(folded1[1] == folded2[1]) &&
|
||||
(folded1[2] == folded2[2]) );
|
||||
} /* utf8codepointcmp */
|
||||
|
||||
|
||||
int __PHYSFS_utf8strcasecmp(const char *str1, const char *str2)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
const PHYSFS_uint32 cp1 = utf8codepoint(&str1);
|
||||
const PHYSFS_uint32 cp2 = utf8codepoint(&str2);
|
||||
if (!utf8codepointcmp(cp1, cp2)) return 0;
|
||||
if (cp1 == 0) return 1;
|
||||
} /* while */
|
||||
|
||||
return 0; /* shouldn't hit this. */
|
||||
} /* __PHYSFS_utf8strcasecmp */
|
||||
|
||||
|
||||
int __PHYSFS_utf8strnicmp(const char *str1, const char *str2, PHYSFS_uint32 n)
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
const PHYSFS_uint32 cp1 = utf8codepoint(&str1);
|
||||
const PHYSFS_uint32 cp2 = utf8codepoint(&str2);
|
||||
if (!utf8codepointcmp(cp1, cp2)) return 0;
|
||||
if (cp1 == 0) return 1;
|
||||
n--;
|
||||
} /* while */
|
||||
|
||||
return 1; /* matched to n chars. */
|
||||
} /* __PHYSFS_utf8strnicmp */
|
||||
|
||||
|
||||
int __PHYSFS_stricmpASCII(const char *str1, const char *str2)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
const char ch1 = *(str1++);
|
||||
const char ch2 = *(str2++);
|
||||
const char cp1 = ((ch1 >= 'A') && (ch1 <= 'Z')) ? (ch1+32) : ch1;
|
||||
const char cp2 = ((ch2 >= 'A') && (ch2 <= 'Z')) ? (ch2+32) : ch2;
|
||||
if (cp1 < cp2)
|
||||
return -1;
|
||||
else if (cp1 > cp2)
|
||||
return 1;
|
||||
else if (cp1 == 0) /* they're both null chars? */
|
||||
return 0;
|
||||
} /* while */
|
||||
|
||||
return 0; /* shouldn't hit this. */
|
||||
} /* __PHYSFS_stricmpASCII */
|
||||
|
||||
|
||||
int __PHYSFS_strnicmpASCII(const char *str1, const char *str2, PHYSFS_uint32 n)
|
||||
{
|
||||
while (n-- > 0)
|
||||
{
|
||||
const char ch1 = *(str1++);
|
||||
const char ch2 = *(str2++);
|
||||
const char cp1 = ((ch1 >= 'A') && (ch1 <= 'Z')) ? (ch1+32) : ch1;
|
||||
const char cp2 = ((ch2 >= 'A') && (ch2 <= 'Z')) ? (ch2+32) : ch2;
|
||||
if (cp1 < cp2)
|
||||
return -1;
|
||||
else if (cp1 > cp2)
|
||||
return 1;
|
||||
else if (cp1 == 0) /* they're both null chars? */
|
||||
return 0;
|
||||
} /* while */
|
||||
|
||||
return 0;
|
||||
} /* __PHYSFS_stricmpASCII */
|
||||
|
||||
|
||||
/* end of physfs_unicode.c ... */
|
||||
|
||||
256
project/jni/physfs/platform/beos.cpp
Normal file
256
project/jni/physfs/platform/beos.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* BeOS platform-dependent support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_platforms.h"
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_BEOS
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_HAIKU
|
||||
#include <os/kernel/OS.h>
|
||||
#include <os/app/Roster.h>
|
||||
#include <os/storage/Volume.h>
|
||||
#include <os/storage/VolumeRoster.h>
|
||||
#include <os/storage/Directory.h>
|
||||
#include <os/storage/Entry.h>
|
||||
#include <os/storage/Path.h>
|
||||
#include <os/kernel/fs_info.h>
|
||||
#include <os/device/scsi.h>
|
||||
#include <os/support/Locker.h>
|
||||
#else
|
||||
#include <be/kernel/OS.h>
|
||||
#include <be/app/Roster.h>
|
||||
#include <be/storage/Volume.h>
|
||||
#include <be/storage/VolumeRoster.h>
|
||||
#include <be/storage/Directory.h>
|
||||
#include <be/storage/Entry.h>
|
||||
#include <be/storage/Path.h>
|
||||
#include <be/kernel/fs_info.h>
|
||||
#include <be/device/scsi.h>
|
||||
#include <be/support/Locker.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "physfs_internal.h"
|
||||
|
||||
|
||||
int __PHYSFS_platformInit(void)
|
||||
{
|
||||
return(1); /* always succeed. */
|
||||
} /* __PHYSFS_platformInit */
|
||||
|
||||
|
||||
int __PHYSFS_platformDeinit(void)
|
||||
{
|
||||
return(1); /* always succeed. */
|
||||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
static char *getMountPoint(const char *devname)
|
||||
{
|
||||
BVolumeRoster mounts;
|
||||
BVolume vol;
|
||||
|
||||
mounts.Rewind();
|
||||
while (mounts.GetNextVolume(&vol) == B_NO_ERROR)
|
||||
{
|
||||
fs_info fsinfo;
|
||||
fs_stat_dev(vol.Device(), &fsinfo);
|
||||
if (strcmp(devname, fsinfo.device_name) == 0)
|
||||
{
|
||||
//char buf[B_FILE_NAME_LENGTH];
|
||||
BDirectory directory;
|
||||
BEntry entry;
|
||||
BPath path;
|
||||
status_t rc;
|
||||
rc = vol.GetRootDirectory(&directory);
|
||||
BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL);
|
||||
rc = directory.GetEntry(&entry);
|
||||
BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL);
|
||||
rc = entry.GetPath(&path);
|
||||
BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL);
|
||||
const char *str = path.Path();
|
||||
BAIL_IF_MACRO(str == NULL, ERR_OS_ERROR, NULL); /* ?! */
|
||||
char *retval = (char *) allocator.Malloc(strlen(str) + 1);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
strcpy(retval, str);
|
||||
return(retval);
|
||||
} /* if */
|
||||
} /* while */
|
||||
|
||||
return(NULL);
|
||||
} /* getMountPoint */
|
||||
|
||||
|
||||
/*
|
||||
* This function is lifted from Simple Directmedia Layer (SDL):
|
||||
* http://www.libsdl.org/
|
||||
*/
|
||||
static void tryDir(const char *d, PHYSFS_StringCallback callback, void *data)
|
||||
{
|
||||
BDirectory dir;
|
||||
dir.SetTo(d);
|
||||
if (dir.InitCheck() != B_NO_ERROR)
|
||||
return;
|
||||
|
||||
dir.Rewind();
|
||||
BEntry entry;
|
||||
while (dir.GetNextEntry(&entry) >= 0)
|
||||
{
|
||||
BPath path;
|
||||
const char *name;
|
||||
entry_ref e;
|
||||
|
||||
if (entry.GetPath(&path) != B_NO_ERROR)
|
||||
continue;
|
||||
|
||||
name = path.Path();
|
||||
|
||||
if (entry.GetRef(&e) != B_NO_ERROR)
|
||||
continue;
|
||||
|
||||
if (entry.IsDirectory())
|
||||
{
|
||||
if (strcmp(e.name, "floppy") != 0)
|
||||
tryDir(name, callback, data);
|
||||
} /* if */
|
||||
|
||||
else
|
||||
{
|
||||
bool add_it = false;
|
||||
int devfd;
|
||||
device_geometry g;
|
||||
|
||||
if (strcmp(e.name, "raw") == 0) /* ignore partitions. */
|
||||
{
|
||||
int devfd = open(name, O_RDONLY);
|
||||
if (devfd >= 0)
|
||||
{
|
||||
if (ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0)
|
||||
{
|
||||
if (g.device_type == B_CD)
|
||||
{
|
||||
char *mntpnt = getMountPoint(name);
|
||||
if (mntpnt != NULL)
|
||||
{
|
||||
callback(data, mntpnt);
|
||||
allocator.Free(mntpnt); /* !!! FIXME: lose this malloc! */
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
close(devfd);
|
||||
} /* else */
|
||||
} /* while */
|
||||
} /* tryDir */
|
||||
|
||||
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
tryDir("/dev/disk", cb, data);
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
static team_id getTeamID(void)
|
||||
{
|
||||
thread_info info;
|
||||
thread_id tid = find_thread(NULL);
|
||||
get_thread_info(tid, &info);
|
||||
return(info.team);
|
||||
} /* getTeamID */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
{
|
||||
image_info info;
|
||||
int32 cookie = 0;
|
||||
|
||||
while (get_next_image_info(0, &cookie, &info) == B_OK) {
|
||||
if (info.type == B_APP_IMAGE)
|
||||
break;
|
||||
}
|
||||
|
||||
BEntry entry(info.name, true);
|
||||
BPath path;
|
||||
status_t rc = entry.GetPath(&path); /* (path) now has binary's path. */
|
||||
assert(rc == B_OK);
|
||||
rc = path.GetParent(&path); /* chop filename, keep directory. */
|
||||
assert(rc == B_OK);
|
||||
const char *str = path.Path();
|
||||
assert(str != NULL);
|
||||
char *retval = (char *) allocator.Malloc(strlen(str) + 1);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
strcpy(retval, str);
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformCalcBaseDir */
|
||||
|
||||
|
||||
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return((PHYSFS_uint64) find_thread(NULL));
|
||||
} /* __PHYSFS_platformGetThreadID */
|
||||
|
||||
|
||||
char *__PHYSFS_platformRealPath(const char *path)
|
||||
{
|
||||
BPath normalized(path, NULL, true); /* force normalization of path. */
|
||||
const char *resolved_path = normalized.Path();
|
||||
BAIL_IF_MACRO(resolved_path == NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
char *retval = (char *) allocator.Malloc(strlen(resolved_path) + 1);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
strcpy(retval, resolved_path);
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformRealPath */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCurrentDir(void)
|
||||
{
|
||||
return(__PHYSFS_platformRealPath(".")); /* let BPath sort it out. */
|
||||
} /* __PHYSFS_platformCurrentDir */
|
||||
|
||||
|
||||
void *__PHYSFS_platformCreateMutex(void)
|
||||
{
|
||||
return(new BLocker("PhysicsFS lock", true));
|
||||
} /* __PHYSFS_platformCreateMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformDestroyMutex(void *mutex)
|
||||
{
|
||||
delete ((BLocker *) mutex);
|
||||
} /* __PHYSFS_platformDestroyMutex */
|
||||
|
||||
|
||||
int __PHYSFS_platformGrabMutex(void *mutex)
|
||||
{
|
||||
return ((BLocker *) mutex)->Lock() ? 1 : 0;
|
||||
} /* __PHYSFS_platformGrabMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex)
|
||||
{
|
||||
((BLocker *) mutex)->Unlock();
|
||||
} /* __PHYSFS_platformReleaseMutex */
|
||||
|
||||
|
||||
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
|
||||
{
|
||||
return(0); /* just use malloc() and friends. */
|
||||
} /* __PHYSFS_platformSetDefaultAllocator */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_BEOS */
|
||||
|
||||
/* end of beos.cpp ... */
|
||||
|
||||
396
project/jni/physfs/platform/macosx.c
Normal file
396
project/jni/physfs/platform/macosx.c
Normal file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Mac OS X support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_platforms.h"
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_MACOSX
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <IOKit/storage/IOMedia.h>
|
||||
#include <IOKit/storage/IOCDMedia.h>
|
||||
#include <IOKit/storage/IODVDMedia.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
/* Seems to get defined in some system header... */
|
||||
#ifdef Free
|
||||
#undef Free
|
||||
#endif
|
||||
|
||||
#include "physfs_internal.h"
|
||||
|
||||
|
||||
/* Wrap PHYSFS_Allocator in a CFAllocator... */
|
||||
static CFAllocatorRef cfallocator = NULL;
|
||||
|
||||
CFStringRef cfallocDesc(const void *info)
|
||||
{
|
||||
return(CFStringCreateWithCString(cfallocator, "PhysicsFS",
|
||||
kCFStringEncodingASCII));
|
||||
} /* cfallocDesc */
|
||||
|
||||
|
||||
static void *cfallocMalloc(CFIndex allocSize, CFOptionFlags hint, void *info)
|
||||
{
|
||||
return allocator.Malloc(allocSize);
|
||||
} /* cfallocMalloc */
|
||||
|
||||
|
||||
static void cfallocFree(void *ptr, void *info)
|
||||
{
|
||||
allocator.Free(ptr);
|
||||
} /* cfallocFree */
|
||||
|
||||
|
||||
static void *cfallocRealloc(void *ptr, CFIndex newsize,
|
||||
CFOptionFlags hint, void *info)
|
||||
{
|
||||
if ((ptr == NULL) || (newsize <= 0))
|
||||
return NULL; /* ADC docs say you should always return NULL here. */
|
||||
return allocator.Realloc(ptr, newsize);
|
||||
} /* cfallocRealloc */
|
||||
|
||||
|
||||
int __PHYSFS_platformInit(void)
|
||||
{
|
||||
/* set up a CFAllocator, so Carbon can use the physfs allocator, too. */
|
||||
CFAllocatorContext ctx;
|
||||
memset(&ctx, '\0', sizeof (ctx));
|
||||
ctx.copyDescription = cfallocDesc;
|
||||
ctx.allocate = cfallocMalloc;
|
||||
ctx.reallocate = cfallocRealloc;
|
||||
ctx.deallocate = cfallocFree;
|
||||
cfallocator = CFAllocatorCreate(kCFAllocatorUseContext, &ctx);
|
||||
BAIL_IF_MACRO(cfallocator == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
return(1); /* success. */
|
||||
} /* __PHYSFS_platformInit */
|
||||
|
||||
|
||||
int __PHYSFS_platformDeinit(void)
|
||||
{
|
||||
CFRelease(cfallocator);
|
||||
cfallocator = NULL;
|
||||
return(1); /* always succeed. */
|
||||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
/* CD-ROM detection code... */
|
||||
|
||||
/*
|
||||
* Code based on sample from Apple Developer Connection:
|
||||
* http://developer.apple.com/samplecode/Sample_Code/Devices_and_Hardware/Disks/VolumeToBSDNode/VolumeToBSDNode.c.htm
|
||||
*/
|
||||
|
||||
static int darwinIsWholeMedia(io_service_t service)
|
||||
{
|
||||
int retval = 0;
|
||||
CFTypeRef wholeMedia;
|
||||
|
||||
if (!IOObjectConformsTo(service, kIOMediaClass))
|
||||
return(0);
|
||||
|
||||
wholeMedia = IORegistryEntryCreateCFProperty(service,
|
||||
CFSTR(kIOMediaWholeKey),
|
||||
cfallocator, 0);
|
||||
if (wholeMedia == NULL)
|
||||
return(0);
|
||||
|
||||
retval = CFBooleanGetValue(wholeMedia);
|
||||
CFRelease(wholeMedia);
|
||||
|
||||
return retval;
|
||||
} /* darwinIsWholeMedia */
|
||||
|
||||
|
||||
static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
|
||||
{
|
||||
int retval = 0;
|
||||
CFMutableDictionaryRef matchingDict;
|
||||
kern_return_t rc;
|
||||
io_iterator_t iter;
|
||||
io_service_t service;
|
||||
|
||||
if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL)
|
||||
return(0);
|
||||
|
||||
rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter);
|
||||
if ((rc != KERN_SUCCESS) || (!iter))
|
||||
return(0);
|
||||
|
||||
service = IOIteratorNext(iter);
|
||||
IOObjectRelease(iter);
|
||||
if (!service)
|
||||
return(0);
|
||||
|
||||
rc = IORegistryEntryCreateIterator(service, kIOServicePlane,
|
||||
kIORegistryIterateRecursively | kIORegistryIterateParents, &iter);
|
||||
|
||||
if (!iter)
|
||||
return(0);
|
||||
|
||||
if (rc != KERN_SUCCESS)
|
||||
{
|
||||
IOObjectRelease(iter);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
IOObjectRetain(service); /* add an extra object reference... */
|
||||
|
||||
do
|
||||
{
|
||||
if (darwinIsWholeMedia(service))
|
||||
{
|
||||
if ( (IOObjectConformsTo(service, kIOCDMediaClass)) ||
|
||||
(IOObjectConformsTo(service, kIODVDMediaClass)) )
|
||||
{
|
||||
retval = 1;
|
||||
} /* if */
|
||||
} /* if */
|
||||
IOObjectRelease(service);
|
||||
} while ((service = IOIteratorNext(iter)) && (!retval));
|
||||
|
||||
IOObjectRelease(iter);
|
||||
IOObjectRelease(service);
|
||||
|
||||
return(retval);
|
||||
} /* darwinIsMountedDisc */
|
||||
|
||||
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
const char *devPrefix = "/dev/";
|
||||
const int prefixLen = strlen(devPrefix);
|
||||
mach_port_t masterPort = 0;
|
||||
struct statfs *mntbufp;
|
||||
int i, mounts;
|
||||
|
||||
if (IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS)
|
||||
BAIL_MACRO(ERR_OS_ERROR, ) /*return void*/;
|
||||
|
||||
mounts = getmntinfo(&mntbufp, MNT_WAIT); /* NOT THREAD SAFE! */
|
||||
for (i = 0; i < mounts; i++)
|
||||
{
|
||||
char *dev = mntbufp[i].f_mntfromname;
|
||||
char *mnt = mntbufp[i].f_mntonname;
|
||||
if (strncmp(dev, devPrefix, prefixLen) != 0) /* a virtual device? */
|
||||
continue;
|
||||
|
||||
dev += prefixLen;
|
||||
if (darwinIsMountedDisc(dev, masterPort))
|
||||
cb(data, mnt);
|
||||
} /* for */
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
static char *convertCFString(CFStringRef cfstr)
|
||||
{
|
||||
CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr),
|
||||
kCFStringEncodingUTF8) + 1;
|
||||
char *retval = (char *) allocator.Malloc(len);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
if (CFStringGetCString(cfstr, retval, len, kCFStringEncodingUTF8))
|
||||
{
|
||||
/* shrink overallocated buffer if possible... */
|
||||
CFIndex newlen = strlen(retval) + 1;
|
||||
if (newlen < len)
|
||||
{
|
||||
void *ptr = allocator.Realloc(retval, newlen);
|
||||
if (ptr != NULL)
|
||||
retval = (char *) ptr;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
else /* probably shouldn't fail, but just in case... */
|
||||
{
|
||||
allocator.Free(retval);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
} /* convertCFString */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
{
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||
FSRef fsref;
|
||||
CFRange cfrange;
|
||||
CFURLRef cfurl = NULL;
|
||||
CFStringRef cfstr = NULL;
|
||||
CFMutableStringRef cfmutstr = NULL;
|
||||
char *retval = NULL;
|
||||
|
||||
BAIL_IF_MACRO(GetProcessBundleLocation(&psn, &fsref) != noErr, NULL, NULL);
|
||||
cfurl = CFURLCreateFromFSRef(cfallocator, &fsref);
|
||||
BAIL_IF_MACRO(cfurl == NULL, NULL, NULL);
|
||||
cfstr = CFURLCopyFileSystemPath(cfurl, kCFURLPOSIXPathStyle);
|
||||
CFRelease(cfurl);
|
||||
BAIL_IF_MACRO(cfstr == NULL, NULL, NULL);
|
||||
cfmutstr = CFStringCreateMutableCopy(cfallocator, 0, cfstr);
|
||||
CFRelease(cfstr);
|
||||
BAIL_IF_MACRO(cfmutstr == NULL, NULL, NULL);
|
||||
|
||||
/* Find last dirsep so we can chop the binary's filename from the path. */
|
||||
cfrange = CFStringFind(cfmutstr, CFSTR("/"), kCFCompareBackwards);
|
||||
if (cfrange.location == kCFNotFound)
|
||||
{
|
||||
assert(0); /* shouldn't ever hit this... */
|
||||
CFRelease(cfmutstr);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
/* chop the "/exename" from the end of the path string... */
|
||||
cfrange.length = CFStringGetLength(cfmutstr) - cfrange.location;
|
||||
CFStringDelete(cfmutstr, cfrange);
|
||||
|
||||
/* If we're an Application Bundle, chop everything but the base. */
|
||||
cfrange = CFStringFind(cfmutstr, CFSTR("/Contents/MacOS"),
|
||||
kCFCompareCaseInsensitive |
|
||||
kCFCompareBackwards |
|
||||
kCFCompareAnchored);
|
||||
|
||||
if (cfrange.location != kCFNotFound)
|
||||
CFStringDelete(cfmutstr, cfrange); /* chop that, too. */
|
||||
|
||||
retval = convertCFString(cfmutstr);
|
||||
CFRelease(cfmutstr);
|
||||
|
||||
return(retval); /* whew. */
|
||||
} /* __PHYSFS_platformCalcBaseDir */
|
||||
|
||||
|
||||
/* !!! FIXME */
|
||||
#define osxerr(x) x
|
||||
|
||||
char *__PHYSFS_platformRealPath(const char *path)
|
||||
{
|
||||
/* The symlink and relative path resolving happens in FSPathMakeRef() */
|
||||
FSRef fsref;
|
||||
CFURLRef cfurl = NULL;
|
||||
CFStringRef cfstr = NULL;
|
||||
char *retval = NULL;
|
||||
OSStatus rc = osxerr(FSPathMakeRef((UInt8 *) path, &fsref, NULL));
|
||||
BAIL_IF_MACRO(rc != noErr, NULL, NULL);
|
||||
|
||||
/* Now get it to spit out a full path. */
|
||||
cfurl = CFURLCreateFromFSRef(cfallocator, &fsref);
|
||||
BAIL_IF_MACRO(cfurl == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
cfstr = CFURLCopyFileSystemPath(cfurl, kCFURLPOSIXPathStyle);
|
||||
CFRelease(cfurl);
|
||||
BAIL_IF_MACRO(cfstr == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
retval = convertCFString(cfstr);
|
||||
CFRelease(cfstr);
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformRealPath */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCurrentDir(void)
|
||||
{
|
||||
return(__PHYSFS_platformRealPath(".")); /* let CFURL sort it out. */
|
||||
} /* __PHYSFS_platformCurrentDir */
|
||||
|
||||
|
||||
/* Platform allocator uses default CFAllocator at PHYSFS_init() time. */
|
||||
|
||||
static CFAllocatorRef cfallocdef = NULL;
|
||||
|
||||
static int macosxAllocatorInit(void)
|
||||
{
|
||||
int retval = 0;
|
||||
cfallocdef = CFAllocatorGetDefault();
|
||||
retval = (cfallocdef != NULL);
|
||||
if (retval)
|
||||
CFRetain(cfallocdef);
|
||||
return(retval);
|
||||
} /* macosxAllocatorInit */
|
||||
|
||||
|
||||
static void macosxAllocatorDeinit(void)
|
||||
{
|
||||
if (cfallocdef != NULL)
|
||||
{
|
||||
CFRelease(cfallocdef);
|
||||
cfallocdef = NULL;
|
||||
} /* if */
|
||||
} /* macosxAllocatorDeinit */
|
||||
|
||||
|
||||
static void *macosxAllocatorMalloc(PHYSFS_uint64 s)
|
||||
{
|
||||
BAIL_IF_MACRO(__PHYSFS_ui64FitsAddressSpace(s), ERR_OUT_OF_MEMORY, NULL);
|
||||
return(CFAllocatorAllocate(cfallocdef, (CFIndex) s, 0));
|
||||
} /* macosxAllocatorMalloc */
|
||||
|
||||
|
||||
static void *macosxAllocatorRealloc(void *ptr, PHYSFS_uint64 s)
|
||||
{
|
||||
BAIL_IF_MACRO(__PHYSFS_ui64FitsAddressSpace(s), ERR_OUT_OF_MEMORY, NULL);
|
||||
return(CFAllocatorReallocate(cfallocdef, ptr, (CFIndex) s, 0));
|
||||
} /* macosxAllocatorRealloc */
|
||||
|
||||
|
||||
static void macosxAllocatorFree(void *ptr)
|
||||
{
|
||||
CFAllocatorDeallocate(cfallocdef, ptr);
|
||||
} /* macosxAllocatorFree */
|
||||
|
||||
|
||||
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
|
||||
{
|
||||
allocator.Init = macosxAllocatorInit;
|
||||
allocator.Deinit = macosxAllocatorDeinit;
|
||||
allocator.Malloc = macosxAllocatorMalloc;
|
||||
allocator.Realloc = macosxAllocatorRealloc;
|
||||
allocator.Free = macosxAllocatorFree;
|
||||
return(1); /* return non-zero: we're supplying custom allocator. */
|
||||
} /* __PHYSFS_platformSetDefaultAllocator */
|
||||
|
||||
|
||||
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return( (PHYSFS_uint64) ((size_t) MPCurrentTaskID()) );
|
||||
} /* __PHYSFS_platformGetThreadID */
|
||||
|
||||
|
||||
void *__PHYSFS_platformCreateMutex(void)
|
||||
{
|
||||
MPCriticalRegionID m = NULL;
|
||||
if (osxerr(MPCreateCriticalRegion(&m)) != noErr)
|
||||
return NULL;
|
||||
return m;
|
||||
} /* __PHYSFS_platformCreateMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformDestroyMutex(void *mutex)
|
||||
{
|
||||
MPCriticalRegionID m = (MPCriticalRegionID) mutex;
|
||||
MPDeleteCriticalRegion(m);
|
||||
} /* __PHYSFS_platformDestroyMutex */
|
||||
|
||||
|
||||
int __PHYSFS_platformGrabMutex(void *mutex)
|
||||
{
|
||||
MPCriticalRegionID m = (MPCriticalRegionID) mutex;
|
||||
if (MPEnterCriticalRegion(m, kDurationForever) != noErr)
|
||||
return(0);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformGrabMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex)
|
||||
{
|
||||
MPCriticalRegionID m = (MPCriticalRegionID) mutex;
|
||||
MPExitCriticalRegion(m);
|
||||
} /* __PHYSFS_platformReleaseMutex */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_MACOSX */
|
||||
|
||||
/* end of macosx.c ... */
|
||||
|
||||
702
project/jni/physfs/platform/os2.c
Normal file
702
project/jni/physfs/platform/os2.c
Normal file
@@ -0,0 +1,702 @@
|
||||
/*
|
||||
* OS/2 support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_platforms.h"
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_OS2
|
||||
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSDATETIME
|
||||
#define INCL_DOSFILEMGR
|
||||
#define INCL_DOSMODULEMGR
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_DOSDEVICES
|
||||
#define INCL_DOSDEVIOCTL
|
||||
#define INCL_DOSMISC
|
||||
#include <os2.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "physfs_internal.h"
|
||||
|
||||
const char *__PHYSFS_platformDirSeparator = "\\";
|
||||
|
||||
|
||||
static const char *get_os2_error_string(APIRET rc)
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case NO_ERROR: return(NULL); /* not an error. */
|
||||
case ERROR_INTERRUPT: return(NULL); /* not an error. */
|
||||
case ERROR_TIMEOUT: return(NULL); /* not an error. */
|
||||
case ERROR_NOT_ENOUGH_MEMORY: return(ERR_OUT_OF_MEMORY);
|
||||
case ERROR_FILE_NOT_FOUND: return(ERR_NO_SUCH_FILE);
|
||||
case ERROR_PATH_NOT_FOUND: return(ERR_NO_SUCH_PATH);
|
||||
case ERROR_ACCESS_DENIED: return(ERR_ACCESS_DENIED);
|
||||
case ERROR_NOT_DOS_DISK: return(ERR_NOT_A_DOS_DISK);
|
||||
case ERROR_SHARING_VIOLATION: return(ERR_SHARING_VIOLATION);
|
||||
case ERROR_CANNOT_MAKE: return(ERR_CANNOT_MAKE);
|
||||
case ERROR_DEVICE_IN_USE: return(ERR_DEV_IN_USE);
|
||||
case ERROR_OPEN_FAILED: return(ERR_OPEN_FAILED);
|
||||
case ERROR_DISK_FULL: return(ERR_DISK_FULL);
|
||||
case ERROR_PIPE_BUSY: return(ERR_PIPE_BUSY);
|
||||
case ERROR_SHARING_BUFFER_EXCEEDED: return(ERR_SHARING_BUF_EXCEEDED);
|
||||
case ERROR_FILENAME_EXCED_RANGE: return(ERR_BAD_FILENAME);
|
||||
case ERROR_META_EXPANSION_TOO_LONG: return(ERR_BAD_FILENAME);
|
||||
case ERROR_TOO_MANY_HANDLES: return(ERR_TOO_MANY_HANDLES);
|
||||
case ERROR_TOO_MANY_OPEN_FILES: return(ERR_TOO_MANY_HANDLES);
|
||||
case ERROR_NO_MORE_SEARCH_HANDLES: return(ERR_TOO_MANY_HANDLES);
|
||||
case ERROR_SEEK_ON_DEVICE: return(ERR_SEEK_ERROR);
|
||||
case ERROR_NEGATIVE_SEEK: return(ERR_SEEK_OUT_OF_RANGE);
|
||||
/*!!! FIXME: Where did this go? case ERROR_DEL_CURRENT_DIRECTORY: return(ERR_DEL_CWD);*/
|
||||
case ERROR_WRITE_PROTECT: return(ERR_WRITE_PROTECT_ERROR);
|
||||
case ERROR_WRITE_FAULT: return(ERR_WRITE_FAULT);
|
||||
case ERROR_LOCK_VIOLATION: return(ERR_LOCK_VIOLATION);
|
||||
case ERROR_GEN_FAILURE: return(ERR_GEN_FAILURE);
|
||||
case ERROR_UNCERTAIN_MEDIA: return(ERR_UNCERTAIN_MEDIA);
|
||||
case ERROR_PROTECTION_VIOLATION: return(ERR_PROT_VIOLATION);
|
||||
case ERROR_BROKEN_PIPE: return(ERR_BROKEN_PIPE);
|
||||
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
case ERROR_INVALID_NAME:
|
||||
case ERROR_INVALID_DRIVE:
|
||||
case ERROR_INVALID_HANDLE:
|
||||
case ERROR_INVALID_FUNCTION:
|
||||
case ERROR_INVALID_LEVEL:
|
||||
case ERROR_INVALID_CATEGORY:
|
||||
case ERROR_DUPLICATE_NAME:
|
||||
case ERROR_BUFFER_OVERFLOW:
|
||||
case ERROR_BAD_LENGTH:
|
||||
case ERROR_BAD_DRIVER_LEVEL:
|
||||
case ERROR_DIRECT_ACCESS_HANDLE:
|
||||
case ERROR_NOT_OWNER:
|
||||
return(ERR_PHYSFS_BAD_OS_CALL);
|
||||
|
||||
default: return(ERR_OS2_GENERIC);
|
||||
} /* switch */
|
||||
|
||||
return(NULL);
|
||||
} /* get_os2_error_string */
|
||||
|
||||
|
||||
static APIRET os2err(APIRET retval)
|
||||
{
|
||||
char buf[128];
|
||||
const char *err = get_os2_error_string(retval);
|
||||
if (err == ERR_OS2_GENERIC)
|
||||
{
|
||||
snprintf(buf, sizeof (buf), ERR_OS2_GENERIC, (int) retval);
|
||||
err = buf;
|
||||
} /* if */
|
||||
|
||||
if (err != NULL)
|
||||
__PHYSFS_setError(err);
|
||||
|
||||
return(retval);
|
||||
} /* os2err */
|
||||
|
||||
|
||||
/* (be gentle, this function isn't very robust.) */
|
||||
static void cvt_path_to_correct_case(char *buf)
|
||||
{
|
||||
char *fname = buf + 3; /* point to first element. */
|
||||
char *ptr = strchr(fname, '\\'); /* find end of first element. */
|
||||
|
||||
buf[0] = toupper(buf[0]); /* capitalize drive letter. */
|
||||
|
||||
/*
|
||||
* Go through each path element, and enumerate its parent dir until
|
||||
* a case-insensitive match is found. If one is (and it SHOULD be)
|
||||
* then overwrite the original element with the correct case.
|
||||
* If there's an error, or the path has vanished for some reason, it
|
||||
* won't hurt to have the original case, so we just keep going.
|
||||
*/
|
||||
while (fname != NULL)
|
||||
{
|
||||
char spec[CCHMAXPATH];
|
||||
FILEFINDBUF3 fb;
|
||||
HDIR hdir = HDIR_CREATE;
|
||||
ULONG count = 1;
|
||||
APIRET rc;
|
||||
|
||||
*(fname - 1) = '\0'; /* isolate parent dir string. */
|
||||
|
||||
strcpy(spec, buf); /* copy isolated parent dir... */
|
||||
strcat(spec, "\\*.*"); /* ...and add wildcard search spec. */
|
||||
|
||||
if (ptr != NULL) /* isolate element to find (fname is the start). */
|
||||
*ptr = '\0';
|
||||
|
||||
rc = DosFindFirst(spec, &hdir, FILE_DIRECTORY,
|
||||
&fb, sizeof (fb), &count, FIL_STANDARD);
|
||||
if (rc == NO_ERROR)
|
||||
{
|
||||
while (count == 1) /* while still entries to enumerate... */
|
||||
{
|
||||
if (__PHYSFS_stricmpASCII(fb.achName, fname) == 0)
|
||||
{
|
||||
strcpy(fname, fb.achName);
|
||||
break; /* there it is. Overwrite and stop searching. */
|
||||
} /* if */
|
||||
|
||||
DosFindNext(hdir, &fb, sizeof (fb), &count);
|
||||
} /* while */
|
||||
DosFindClose(hdir);
|
||||
} /* if */
|
||||
|
||||
*(fname - 1) = '\\'; /* unisolate parent dir. */
|
||||
fname = ptr; /* point to next element. */
|
||||
if (ptr != NULL)
|
||||
{
|
||||
*ptr = '\\'; /* unisolate element. */
|
||||
ptr = strchr(++fname, '\\'); /* find next element. */
|
||||
} /* if */
|
||||
} /* while */
|
||||
} /* cvt_file_to_correct_case */
|
||||
|
||||
|
||||
static char *baseDir = NULL;
|
||||
|
||||
int __PHYSFS_platformInit(void)
|
||||
{
|
||||
char buf[CCHMAXPATH];
|
||||
APIRET rc;
|
||||
PTIB ptib;
|
||||
PPIB ppib;
|
||||
PHYSFS_sint32 len;
|
||||
|
||||
assert(baseDir == NULL);
|
||||
BAIL_IF_MACRO(os2err(DosGetInfoBlocks(&ptib, &ppib)) != NO_ERROR, NULL, 0);
|
||||
rc = DosQueryModuleName(ppib->pib_hmte, sizeof (buf), (PCHAR) buf);
|
||||
BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, 0);
|
||||
|
||||
/* chop off filename, leave path. */
|
||||
for (len = strlen(buf) - 1; len >= 0; len--)
|
||||
{
|
||||
if (buf[len] == '\\')
|
||||
{
|
||||
buf[len] = '\0';
|
||||
break;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
assert(len > 0); /* should have been a "x:\\" on the front on string. */
|
||||
|
||||
/* The string is capitalized! Figure out the REAL case... */
|
||||
cvt_path_to_correct_case(buf);
|
||||
|
||||
baseDir = (char *) allocator.Malloc(len + 1);
|
||||
BAIL_IF_MACRO(baseDir == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
strcpy(baseDir, buf);
|
||||
return(1); /* success. */
|
||||
} /* __PHYSFS_platformInit */
|
||||
|
||||
|
||||
int __PHYSFS_platformDeinit(void)
|
||||
{
|
||||
assert(baseDir != NULL);
|
||||
allocator.Free(baseDir);
|
||||
baseDir = NULL;
|
||||
return(1); /* success. */
|
||||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
static int disc_is_inserted(ULONG drive)
|
||||
{
|
||||
int rc;
|
||||
char buf[20];
|
||||
DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
|
||||
rc = DosQueryFSInfo(drive + 1, FSIL_VOLSER, buf, sizeof (buf));
|
||||
DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
|
||||
return(rc == NO_ERROR);
|
||||
} /* is_cdrom_inserted */
|
||||
|
||||
|
||||
/* looks like "CD01" in ASCII (littleendian)...used for an ioctl. */
|
||||
#define CD01 0x31304443
|
||||
|
||||
static int is_cdrom_drive(ULONG drive)
|
||||
{
|
||||
PHYSFS_uint32 param, data;
|
||||
ULONG ul1, ul2;
|
||||
APIRET rc;
|
||||
HFILE hfile = NULLHANDLE;
|
||||
char drivename[3] = { 'A' + drive, ':', '\0' };
|
||||
|
||||
rc = DosOpen(drivename, &hfile, &ul1, 0, 0,
|
||||
OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
|
||||
OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
|
||||
OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE, NULL);
|
||||
BAIL_IF_MACRO(rc != NO_ERROR, NULL, 0);
|
||||
|
||||
data = 0;
|
||||
param = PHYSFS_swapULE32(CD01);
|
||||
ul1 = ul2 = sizeof (PHYSFS_uint32);
|
||||
rc = DosDevIOCtl(hfile, IOCTL_CDROMDISK, CDROMDISK_GETDRIVER,
|
||||
¶m, sizeof (param), &ul1, &data, sizeof (data), &ul2);
|
||||
|
||||
DosClose(hfile);
|
||||
return((rc == NO_ERROR) && (PHYSFS_swapULE32(data) == CD01));
|
||||
} /* is_cdrom_drive */
|
||||
|
||||
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
ULONG dummy = 0;
|
||||
ULONG drivemap = 0;
|
||||
ULONG i, bit;
|
||||
APIRET rc = DosQueryCurrentDisk(&dummy, &drivemap);
|
||||
if (os2err(rc) != NO_ERROR)
|
||||
return;
|
||||
|
||||
for (i = 0, bit = 1; i < 26; i++, bit <<= 1)
|
||||
{
|
||||
if (drivemap & bit) /* this logical drive exists. */
|
||||
{
|
||||
if ((is_cdrom_drive(i)) && (disc_is_inserted(i)))
|
||||
{
|
||||
char drive[4] = "x:\\";
|
||||
drive[0] = ('A' + i);
|
||||
cb(data, drive);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* for */
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
{
|
||||
char *retval = (char *) allocator.Malloc(strlen(baseDir) + 1);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
strcpy(retval, baseDir); /* calculated at init time. */
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformCalcBaseDir */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserName(void)
|
||||
{
|
||||
return(NULL); /* (*shrug*) */
|
||||
} /* __PHYSFS_platformGetUserName */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserDir(void)
|
||||
{
|
||||
return(__PHYSFS_platformCalcBaseDir(NULL));
|
||||
} /* __PHYSFS_platformGetUserDir */
|
||||
|
||||
|
||||
int __PHYSFS_platformExists(const char *fname)
|
||||
{
|
||||
FILESTATUS3 fs;
|
||||
APIRET rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs, sizeof (fs));
|
||||
return(os2err(rc) == NO_ERROR);
|
||||
} /* __PHYSFS_platformExists */
|
||||
|
||||
|
||||
int __PHYSFS_platformIsSymLink(const char *fname)
|
||||
{
|
||||
return(0); /* no symlinks in OS/2. */
|
||||
} /* __PHYSFS_platformIsSymlink */
|
||||
|
||||
|
||||
int __PHYSFS_platformIsDirectory(const char *fname)
|
||||
{
|
||||
FILESTATUS3 fs;
|
||||
APIRET rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs, sizeof (fs));
|
||||
BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, 0)
|
||||
return((fs.attrFile & FILE_DIRECTORY) != 0);
|
||||
} /* __PHYSFS_platformIsDirectory */
|
||||
|
||||
|
||||
/* !!! FIXME: can we lose the malloc here? */
|
||||
char *__PHYSFS_platformCvtToDependent(const char *prepend,
|
||||
const char *dirName,
|
||||
const char *append)
|
||||
{
|
||||
int len = ((prepend) ? strlen(prepend) : 0) +
|
||||
((append) ? strlen(append) : 0) +
|
||||
strlen(dirName) + 1;
|
||||
char *retval = allocator.Malloc(len);
|
||||
char *p;
|
||||
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
if (prepend)
|
||||
strcpy(retval, prepend);
|
||||
else
|
||||
retval[0] = '\0';
|
||||
|
||||
strcat(retval, dirName);
|
||||
|
||||
if (append)
|
||||
strcat(retval, append);
|
||||
|
||||
for (p = strchr(retval, '/'); p != NULL; p = strchr(p + 1, '/'))
|
||||
*p = '\\';
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformCvtToDependent */
|
||||
|
||||
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_EnumFilesCallback callback,
|
||||
const char *origdir,
|
||||
void *callbackdata)
|
||||
{
|
||||
char spec[CCHMAXPATH];
|
||||
FILEFINDBUF3 fb;
|
||||
HDIR hdir = HDIR_CREATE;
|
||||
ULONG count = 1;
|
||||
APIRET rc;
|
||||
|
||||
if (strlen(dirname) > sizeof (spec) - 5)
|
||||
{
|
||||
__PHYSFS_setError(ERR_BAD_FILENAME);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
strcpy(spec, dirname);
|
||||
strcat(spec, (spec[strlen(spec) - 1] != '\\') ? "\\*.*" : "*.*");
|
||||
|
||||
rc = DosFindFirst(spec, &hdir,
|
||||
FILE_DIRECTORY | FILE_ARCHIVED |
|
||||
FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM,
|
||||
&fb, sizeof (fb), &count, FIL_STANDARD);
|
||||
|
||||
if (os2err(rc) != NO_ERROR)
|
||||
return;
|
||||
|
||||
while (count == 1)
|
||||
{
|
||||
if ((strcmp(fb.achName, ".") != 0) && (strcmp(fb.achName, "..") != 0))
|
||||
callback(callbackdata, origdir, fb.achName);
|
||||
|
||||
DosFindNext(hdir, &fb, sizeof (fb), &count);
|
||||
} /* while */
|
||||
|
||||
DosFindClose(hdir);
|
||||
} /* __PHYSFS_platformEnumerateFiles */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCurrentDir(void)
|
||||
{
|
||||
char *retval;
|
||||
ULONG currentDisk;
|
||||
ULONG dummy;
|
||||
ULONG pathSize = 0;
|
||||
APIRET rc;
|
||||
BYTE byte;
|
||||
|
||||
rc = DosQueryCurrentDisk(¤tDisk, &dummy);
|
||||
BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, NULL);
|
||||
|
||||
/* The first call just tells us how much space we need for the string. */
|
||||
rc = DosQueryCurrentDir(currentDisk, &byte, &pathSize);
|
||||
pathSize++; /* Add space for null terminator. */
|
||||
retval = (char *) allocator.Malloc(pathSize + 3); /* plus "x:\\" */
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
/* Actually get the string this time. */
|
||||
rc = DosQueryCurrentDir(currentDisk, (PBYTE) (retval + 3), &pathSize);
|
||||
if (os2err(rc) != NO_ERROR)
|
||||
{
|
||||
allocator.Free(retval);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
retval[0] = ('A' + (currentDisk - 1));
|
||||
retval[1] = ':';
|
||||
retval[2] = '\\';
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformCurrentDir */
|
||||
|
||||
|
||||
char *__PHYSFS_platformRealPath(const char *path)
|
||||
{
|
||||
char buf[CCHMAXPATH];
|
||||
char *retval;
|
||||
APIRET rc = DosQueryPathInfo(path, FIL_QUERYFULLNAME, buf, sizeof (buf));
|
||||
BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, NULL);
|
||||
retval = (char *) allocator.Malloc(strlen(buf) + 1);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
strcpy(retval, buf);
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformRealPath */
|
||||
|
||||
|
||||
int __PHYSFS_platformMkDir(const char *path)
|
||||
{
|
||||
return(os2err(DosCreateDir(path, NULL)) == NO_ERROR);
|
||||
} /* __PHYSFS_platformMkDir */
|
||||
|
||||
|
||||
void *__PHYSFS_platformOpenRead(const char *filename)
|
||||
{
|
||||
ULONG actionTaken = 0;
|
||||
HFILE hfile = NULLHANDLE;
|
||||
|
||||
/*
|
||||
* File must be opened SHARE_DENYWRITE and ACCESS_READONLY, otherwise
|
||||
* DosQueryFileInfo() will fail if we try to get a file length, etc.
|
||||
*/
|
||||
os2err(DosOpen(filename, &hfile, &actionTaken, 0, FILE_NORMAL,
|
||||
OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
|
||||
OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_LOCALITY |
|
||||
OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE |
|
||||
OPEN_ACCESS_READONLY, NULL));
|
||||
|
||||
return((void *) hfile);
|
||||
} /* __PHYSFS_platformOpenRead */
|
||||
|
||||
|
||||
void *__PHYSFS_platformOpenWrite(const char *filename)
|
||||
{
|
||||
ULONG actionTaken = 0;
|
||||
HFILE hfile = NULLHANDLE;
|
||||
|
||||
/*
|
||||
* File must be opened SHARE_DENYWRITE and ACCESS_READWRITE, otherwise
|
||||
* DosQueryFileInfo() will fail if we try to get a file length, etc.
|
||||
*/
|
||||
os2err(DosOpen(filename, &hfile, &actionTaken, 0, FILE_NORMAL,
|
||||
OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
|
||||
OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_LOCALITY |
|
||||
OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE |
|
||||
OPEN_ACCESS_READWRITE, NULL));
|
||||
|
||||
return((void *) hfile);
|
||||
} /* __PHYSFS_platformOpenWrite */
|
||||
|
||||
|
||||
void *__PHYSFS_platformOpenAppend(const char *filename)
|
||||
{
|
||||
ULONG dummy = 0;
|
||||
HFILE hfile = NULLHANDLE;
|
||||
APIRET rc;
|
||||
|
||||
/*
|
||||
* File must be opened SHARE_DENYWRITE and ACCESS_READWRITE, otherwise
|
||||
* DosQueryFileInfo() will fail if we try to get a file length, etc.
|
||||
*/
|
||||
rc = os2err(DosOpen(filename, &hfile, &dummy, 0, FILE_NORMAL,
|
||||
OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
|
||||
OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_LOCALITY |
|
||||
OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE |
|
||||
OPEN_ACCESS_READWRITE, NULL));
|
||||
|
||||
if (rc == NO_ERROR)
|
||||
{
|
||||
if (os2err(DosSetFilePtr(hfile, 0, FILE_END, &dummy)) != NO_ERROR)
|
||||
{
|
||||
DosClose(hfile);
|
||||
hfile = NULLHANDLE;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
return((void *) hfile);
|
||||
} /* __PHYSFS_platformOpenAppend */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
|
||||
PHYSFS_uint32 size, PHYSFS_uint32 count)
|
||||
{
|
||||
HFILE hfile = (HFILE) opaque;
|
||||
PHYSFS_sint64 retval;
|
||||
ULONG br;
|
||||
|
||||
for (retval = 0; retval < count; retval++)
|
||||
{
|
||||
os2err(DosRead(hfile, buffer, size, &br));
|
||||
if (br < size)
|
||||
{
|
||||
DosSetFilePtr(hfile, -br, FILE_CURRENT, &br); /* try to cleanup. */
|
||||
return(retval);
|
||||
} /* if */
|
||||
|
||||
buffer = (void *) ( ((char *) buffer) + size );
|
||||
} /* for */
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformRead */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
|
||||
PHYSFS_uint32 size, PHYSFS_uint32 count)
|
||||
{
|
||||
HFILE hfile = (HFILE) opaque;
|
||||
PHYSFS_sint64 retval;
|
||||
ULONG bw;
|
||||
|
||||
for (retval = 0; retval < count; retval++)
|
||||
{
|
||||
os2err(DosWrite(hfile, buffer, size, &bw));
|
||||
if (bw < size)
|
||||
{
|
||||
DosSetFilePtr(hfile, -bw, FILE_CURRENT, &bw); /* try to cleanup. */
|
||||
return(retval);
|
||||
} /* if */
|
||||
|
||||
buffer = (void *) ( ((char *) buffer) + size );
|
||||
} /* for */
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformWrite */
|
||||
|
||||
|
||||
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
|
||||
{
|
||||
ULONG dummy;
|
||||
HFILE hfile = (HFILE) opaque;
|
||||
LONG dist = (LONG) pos;
|
||||
|
||||
/* hooray for 32-bit filesystem limits! :) */
|
||||
BAIL_IF_MACRO((PHYSFS_uint64) dist != pos, ERR_SEEK_OUT_OF_RANGE, 0);
|
||||
|
||||
return(os2err(DosSetFilePtr(hfile, dist, FILE_BEGIN, &dummy)) == NO_ERROR);
|
||||
} /* __PHYSFS_platformSeek */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
|
||||
{
|
||||
ULONG pos;
|
||||
HFILE hfile = (HFILE) opaque;
|
||||
APIRET rc = os2err(DosSetFilePtr(hfile, 0, FILE_CURRENT, &pos));
|
||||
BAIL_IF_MACRO(rc != NO_ERROR, NULL, -1);
|
||||
return((PHYSFS_sint64) pos);
|
||||
} /* __PHYSFS_platformTell */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
|
||||
{
|
||||
FILESTATUS3 fs;
|
||||
HFILE hfile = (HFILE) opaque;
|
||||
APIRET rc = DosQueryFileInfo(hfile, FIL_STANDARD, &fs, sizeof (fs));
|
||||
BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, -1);
|
||||
return((PHYSFS_sint64) fs.cbFile);
|
||||
} /* __PHYSFS_platformFileLength */
|
||||
|
||||
|
||||
int __PHYSFS_platformEOF(void *opaque)
|
||||
{
|
||||
PHYSFS_sint64 len, pos;
|
||||
|
||||
len = __PHYSFS_platformFileLength(opaque);
|
||||
BAIL_IF_MACRO(len == -1, NULL, 1); /* (*shrug*) */
|
||||
pos = __PHYSFS_platformTell(opaque);
|
||||
BAIL_IF_MACRO(pos == -1, NULL, 1); /* (*shrug*) */
|
||||
|
||||
return(pos >= len);
|
||||
} /* __PHYSFS_platformEOF */
|
||||
|
||||
|
||||
int __PHYSFS_platformFlush(void *opaque)
|
||||
{
|
||||
return(os2err(DosResetBuffer((HFILE) opaque)) == NO_ERROR);
|
||||
} /* __PHYSFS_platformFlush */
|
||||
|
||||
|
||||
int __PHYSFS_platformClose(void *opaque)
|
||||
{
|
||||
return(os2err(DosClose((HFILE) opaque)) == NO_ERROR);
|
||||
} /* __PHYSFS_platformClose */
|
||||
|
||||
|
||||
int __PHYSFS_platformDelete(const char *path)
|
||||
{
|
||||
if (__PHYSFS_platformIsDirectory(path))
|
||||
return(os2err(DosDeleteDir(path)) == NO_ERROR);
|
||||
|
||||
return(os2err(DosDelete(path)) == NO_ERROR);
|
||||
} /* __PHYSFS_platformDelete */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
|
||||
{
|
||||
PHYSFS_sint64 retval;
|
||||
struct tm tm;
|
||||
FILESTATUS3 fs;
|
||||
APIRET rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs, sizeof (fs));
|
||||
BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, -1);
|
||||
|
||||
/* Convert to a format that mktime() can grok... */
|
||||
tm.tm_sec = ((PHYSFS_uint32) fs.ftimeLastWrite.twosecs) * 2;
|
||||
tm.tm_min = fs.ftimeLastWrite.minutes;
|
||||
tm.tm_hour = fs.ftimeLastWrite.hours;
|
||||
tm.tm_mday = fs.fdateLastWrite.day;
|
||||
tm.tm_mon = fs.fdateLastWrite.month;
|
||||
tm.tm_year = ((PHYSFS_uint32) fs.fdateLastWrite.year) + 80;
|
||||
tm.tm_wday = -1 /*st_localtz.wDayOfWeek*/;
|
||||
tm.tm_yday = -1;
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
/* Convert to a format PhysicsFS can grok... */
|
||||
retval = (PHYSFS_sint64) mktime(&tm);
|
||||
BAIL_IF_MACRO(retval == -1, strerror(errno), -1);
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformGetLastModTime */
|
||||
|
||||
|
||||
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
PTIB ptib;
|
||||
PPIB ppib;
|
||||
|
||||
/*
|
||||
* Allegedly, this API never fails, but we'll punt and return a
|
||||
* default value (zero might as well do) if it does.
|
||||
*/
|
||||
BAIL_IF_MACRO(os2err(DosGetInfoBlocks(&ptib, &ppib)) != NO_ERROR, 0, 0);
|
||||
return((PHYSFS_uint64) ptib->tib_ordinal);
|
||||
} /* __PHYSFS_platformGetThreadID */
|
||||
|
||||
|
||||
void *__PHYSFS_platformCreateMutex(void)
|
||||
{
|
||||
HMTX hmtx = NULLHANDLE;
|
||||
os2err(DosCreateMutexSem(NULL, &hmtx, 0, 0));
|
||||
return((void *) hmtx);
|
||||
} /* __PHYSFS_platformCreateMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformDestroyMutex(void *mutex)
|
||||
{
|
||||
DosCloseMutexSem((HMTX) mutex);
|
||||
} /* __PHYSFS_platformDestroyMutex */
|
||||
|
||||
|
||||
int __PHYSFS_platformGrabMutex(void *mutex)
|
||||
{
|
||||
/* Do _NOT_ call os2err() (which sets the physfs error msg) in here! */
|
||||
return(DosRequestMutexSem((HMTX) mutex, SEM_INDEFINITE_WAIT) == NO_ERROR);
|
||||
} /* __PHYSFS_platformGrabMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex)
|
||||
{
|
||||
DosReleaseMutexSem((HMTX) mutex);
|
||||
} /* __PHYSFS_platformReleaseMutex */
|
||||
|
||||
|
||||
/* !!! FIXME: Don't use C runtime for allocators? */
|
||||
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
|
||||
{
|
||||
return(0); /* just use malloc() and friends. */
|
||||
} /* __PHYSFS_platformSetDefaultAllocator */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_OS2 */
|
||||
|
||||
/* end of os2.c ... */
|
||||
|
||||
608
project/jni/physfs/platform/pocketpc.c
Normal file
608
project/jni/physfs/platform/pocketpc.c
Normal file
@@ -0,0 +1,608 @@
|
||||
/*
|
||||
* PocketPC support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_platforms.h"
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_POCKETPC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "physfs_internal.h"
|
||||
|
||||
#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
|
||||
#define INVALID_SET_FILE_POINTER 0xFFFFFFFF
|
||||
typedef struct
|
||||
{
|
||||
HANDLE handle;
|
||||
int readonly;
|
||||
} winCEfile;
|
||||
|
||||
|
||||
const char *__PHYSFS_platformDirSeparator = "\\";
|
||||
static char *userDir = NULL;
|
||||
|
||||
/*
|
||||
* Figure out what the last failing Win32 API call was, and
|
||||
* generate a human-readable string for the error message.
|
||||
*
|
||||
* The return value is a static buffer that is overwritten with
|
||||
* each call to this function.
|
||||
*/
|
||||
static const char *win32strerror(void)
|
||||
{
|
||||
static TCHAR msgbuf[255];
|
||||
TCHAR *ptr = msgbuf;
|
||||
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
|
||||
msgbuf,
|
||||
sizeof (msgbuf) / sizeof (TCHAR),
|
||||
NULL
|
||||
);
|
||||
|
||||
/* chop off newlines. */
|
||||
for (ptr = msgbuf; *ptr; ptr++)
|
||||
{
|
||||
if ((*ptr == '\n') || (*ptr == '\r'))
|
||||
{
|
||||
*ptr = ' ';
|
||||
break;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
return((const char *) msgbuf);
|
||||
} /* win32strerror */
|
||||
|
||||
|
||||
/* !!! FIXME: need to check all of these for NULLs. */
|
||||
#define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \
|
||||
if (str == NULL) \
|
||||
w_assignto = NULL; \
|
||||
else { \
|
||||
const PHYSFS_uint64 len = (PHYSFS_uint64) ((strlen(str) * 4) + 1); \
|
||||
w_assignto = (char *) __PHYSFS_smallAlloc(len); \
|
||||
PHYSFS_uc2fromutf8(str, (PHYSFS_uint16 *) w_assignto, len); \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
static char *getExePath()
|
||||
{
|
||||
DWORD buflen;
|
||||
int success = 0;
|
||||
TCHAR *ptr = NULL;
|
||||
TCHAR *retval = (TCHAR*) allocator.Malloc(sizeof (TCHAR) * (MAX_PATH + 1));
|
||||
char *charretval;
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
retval[0] = _T('\0');
|
||||
/* !!! FIXME: don't preallocate here? */
|
||||
/* !!! FIXME: use smallAlloc? */
|
||||
buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
|
||||
if (buflen <= 0)
|
||||
__PHYSFS_setError(win32strerror());
|
||||
else
|
||||
{
|
||||
retval[buflen] = '\0'; /* does API always null-terminate this? */
|
||||
ptr = retval+buflen;
|
||||
while( ptr != retval )
|
||||
{
|
||||
if( *ptr != _T('\\') )
|
||||
*ptr-- = _T('\0');
|
||||
else
|
||||
break;
|
||||
} /* while */
|
||||
success = 1;
|
||||
} /* else */
|
||||
|
||||
if (!success)
|
||||
{
|
||||
allocator.Free(retval);
|
||||
return(NULL); /* physfs error message will be set, above. */
|
||||
} /* if */
|
||||
|
||||
buflen = (buflen * 4) + 1;
|
||||
charretval = (char *) allocator.Malloc(buflen);
|
||||
if (charretval != NULL)
|
||||
PHYSFS_utf8fromucs2((const PHYSFS_uint16 *) retval, charretval, buflen);
|
||||
allocator.Free(retval);
|
||||
return(charretval); /* w00t. */
|
||||
} /* getExePath */
|
||||
|
||||
|
||||
int __PHYSFS_platformInit(void)
|
||||
{
|
||||
userDir = getExePath();
|
||||
BAIL_IF_MACRO(userDir == NULL, NULL, 0); /* failed? */
|
||||
return(1); /* always succeed. */
|
||||
} /* __PHYSFS_platformInit */
|
||||
|
||||
|
||||
int __PHYSFS_platformDeinit(void)
|
||||
{
|
||||
allocator.Free(userDir);
|
||||
return(1); /* always succeed. */
|
||||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
/* no-op on this platform. */
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
{
|
||||
return(getExePath());
|
||||
} /* __PHYSFS_platformCalcBaseDir */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserName(void)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
|
||||
} /* __PHYSFS_platformGetUserName */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserDir(void)
|
||||
{
|
||||
return userDir;
|
||||
BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
|
||||
} /* __PHYSFS_platformGetUserDir */
|
||||
|
||||
|
||||
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return(1); /* single threaded. */
|
||||
} /* __PHYSFS_platformGetThreadID */
|
||||
|
||||
|
||||
int __PHYSFS_platformExists(const char *fname)
|
||||
{
|
||||
int retval = 0;
|
||||
wchar_t *w_fname = NULL;
|
||||
|
||||
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
|
||||
if (w_fname != NULL)
|
||||
retval = (GetFileAttributes(w_fname) != INVALID_FILE_ATTRIBUTES);
|
||||
__PHYSFS_smallFree(w_fname);
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformExists */
|
||||
|
||||
|
||||
int __PHYSFS_platformIsSymLink(const char *fname)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
|
||||
} /* __PHYSFS_platformIsSymlink */
|
||||
|
||||
|
||||
int __PHYSFS_platformIsDirectory(const char *fname)
|
||||
{
|
||||
int retval = 0;
|
||||
wchar_t *w_fname = NULL;
|
||||
|
||||
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
|
||||
if (w_fname != NULL)
|
||||
retval = ((GetFileAttributes(w_fname) & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
||||
__PHYSFS_smallFree(w_fname);
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformIsDirectory */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCvtToDependent(const char *prepend,
|
||||
const char *dirName,
|
||||
const char *append)
|
||||
{
|
||||
int len = ((prepend) ? strlen(prepend) : 0) +
|
||||
((append) ? strlen(append) : 0) +
|
||||
strlen(dirName) + 1;
|
||||
char *retval = (char *) allocator.Malloc(len);
|
||||
char *p;
|
||||
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
if (prepend)
|
||||
strcpy(retval, prepend);
|
||||
else
|
||||
retval[0] = '\0';
|
||||
|
||||
strcat(retval, dirName);
|
||||
|
||||
if (append)
|
||||
strcat(retval, append);
|
||||
|
||||
for (p = strchr(retval, '/'); p != NULL; p = strchr(p + 1, '/'))
|
||||
*p = '\\';
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformCvtToDependent */
|
||||
|
||||
|
||||
static int doEnumCallback(const wchar_t *w_fname)
|
||||
{
|
||||
const PHYSFS_uint64 len = (PHYSFS_uint64) ((wcslen(w_fname) * 4) + 1);
|
||||
char *str = (char *) __PHYSFS_smallAlloc(len);
|
||||
PHYSFS_utf8fromucs2((const PHYSFS_uint16 *) w_fname, str, len);
|
||||
callback(callbackdata, origdir, str);
|
||||
__PHYSFS_smallFree(str);
|
||||
return 1;
|
||||
} /* doEnumCallback */
|
||||
|
||||
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_EnumFilesCallback callback,
|
||||
const char *origdir,
|
||||
void *callbackdata)
|
||||
{
|
||||
HANDLE dir;
|
||||
WIN32_FIND_DATA ent;
|
||||
char *SearchPath;
|
||||
wchar_t *w_SearchPath;
|
||||
size_t len = strlen(dirname);
|
||||
|
||||
/* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
|
||||
SearchPath = (char *) __PHYSFS_smallAlloc(len + 3);
|
||||
BAIL_IF_MACRO(SearchPath == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
/* Copy current dirname */
|
||||
strcpy(SearchPath, dirname);
|
||||
|
||||
/* if there's no '\\' at the end of the path, stick one in there. */
|
||||
if (SearchPath[len - 1] != '\\')
|
||||
{
|
||||
SearchPath[len++] = '\\';
|
||||
SearchPath[len] = '\0';
|
||||
} /* if */
|
||||
|
||||
/* Append the "*" to the end of the string */
|
||||
strcat(SearchPath, "*");
|
||||
|
||||
UTF8_TO_UNICODE_STACK_MACRO(w_SearchPath, SearchPath);
|
||||
__PHYSFS_smallFree(SearchPath);
|
||||
dir = FindFirstFile(w_SearchPath, &ent);
|
||||
__PHYSFS_smallFree(w_SearchPath);
|
||||
|
||||
if (dir == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
const char *str = NULL;
|
||||
|
||||
if (wcscmp(ent.cFileName, L".") == 0)
|
||||
continue;
|
||||
|
||||
if (wcscmp(ent.cFileName, L"..") == 0)
|
||||
continue;
|
||||
|
||||
if (!doEnumCallback(ent.cFileName))
|
||||
break;
|
||||
} while (FindNextFile(dir, &ent) != 0);
|
||||
|
||||
FindClose(dir);
|
||||
} /* __PHYSFS_platformEnumerateFiles */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCurrentDir(void)
|
||||
{
|
||||
return("\\");
|
||||
} /* __PHYSFS_platformCurrentDir */
|
||||
|
||||
|
||||
char *__PHYSFS_platformRealPath(const char *path)
|
||||
{
|
||||
char *retval = (char *) allocator.Malloc(strlen(path) + 1);
|
||||
strcpy(retval,path);
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformRealPath */
|
||||
|
||||
|
||||
int __PHYSFS_platformMkDir(const char *path)
|
||||
{
|
||||
int retval = 0;
|
||||
wchar_t *w_path = NULL;
|
||||
UTF8_TO_UNICODE_STACK_MACRO(w_path, path);
|
||||
if (w_path != NULL)
|
||||
{
|
||||
retval = CreateDirectory(w_path, NULL);
|
||||
__PHYSFS_smallFree(w_fname);
|
||||
} /* if */
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformMkDir */
|
||||
|
||||
|
||||
static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly)
|
||||
{
|
||||
HANDLE fileHandle;
|
||||
winCEfile *retval;
|
||||
wchar_t *w_fname = NULL;
|
||||
|
||||
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
|
||||
fileHandle = CreateFile(w_fname, mode, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
__PHYSFS_smallFree(w_fname);
|
||||
|
||||
BAIL_IF_MACRO(fileHandle == INVALID_HANDLE_VALUE, win32strerror(), NULL);
|
||||
|
||||
retval = (winCEfile *) allocator.Malloc(sizeof (winCEfile));
|
||||
if (retval == NULL)
|
||||
{
|
||||
CloseHandle(fileHandle);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
} /* if */
|
||||
|
||||
retval->readonly = rdonly;
|
||||
retval->handle = fileHandle;
|
||||
return(retval);
|
||||
} /* doOpen */
|
||||
|
||||
|
||||
void *__PHYSFS_platformOpenRead(const char *filename)
|
||||
{
|
||||
return(doOpen(filename, GENERIC_READ, OPEN_EXISTING, 1));
|
||||
} /* __PHYSFS_platformOpenRead */
|
||||
|
||||
|
||||
void *__PHYSFS_platformOpenWrite(const char *filename)
|
||||
{
|
||||
return(doOpen(filename, GENERIC_WRITE, CREATE_ALWAYS, 0));
|
||||
} /* __PHYSFS_platformOpenWrite */
|
||||
|
||||
|
||||
void *__PHYSFS_platformOpenAppend(const char *filename)
|
||||
{
|
||||
void *retval = doOpen(filename, GENERIC_WRITE, OPEN_ALWAYS, 0);
|
||||
if (retval != NULL)
|
||||
{
|
||||
HANDLE h = ((winCEfile *) retval)->handle;
|
||||
if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
const char *err = win32strerror();
|
||||
CloseHandle(h);
|
||||
allocator.Free(retval);
|
||||
BAIL_MACRO(err, NULL);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
|
||||
} /* __PHYSFS_platformOpenAppend */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
|
||||
PHYSFS_uint32 size, PHYSFS_uint32 count)
|
||||
{
|
||||
HANDLE Handle = ((winCEfile *) opaque)->handle;
|
||||
DWORD CountOfBytesRead;
|
||||
PHYSFS_sint64 retval;
|
||||
|
||||
/* Read data from the file */
|
||||
/*!!! - uint32 might be a greater # than DWORD */
|
||||
if (!ReadFile(Handle, buffer, count * size, &CountOfBytesRead, NULL))
|
||||
{
|
||||
retval = -1;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
/* Return the number of "objects" read. */
|
||||
/* !!! - What if not the right amount of bytes was read to make an object? */
|
||||
retval = CountOfBytesRead / size;
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
|
||||
} /* __PHYSFS_platformRead */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
|
||||
PHYSFS_uint32 size, PHYSFS_uint32 count)
|
||||
{
|
||||
HANDLE Handle = ((winCEfile *) opaque)->handle;
|
||||
DWORD CountOfBytesWritten;
|
||||
PHYSFS_sint64 retval;
|
||||
|
||||
/* Read data from the file */
|
||||
/*!!! - uint32 might be a greater # than DWORD */
|
||||
if (!WriteFile(Handle, buffer, count * size, &CountOfBytesWritten, NULL))
|
||||
{
|
||||
retval = -1;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
/* Return the number of "objects" read. */
|
||||
/*!!! - What if not the right number of bytes was written? */
|
||||
retval = CountOfBytesWritten / size;
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
|
||||
} /* __PHYSFS_platformWrite */
|
||||
|
||||
|
||||
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
|
||||
{
|
||||
HANDLE Handle = ((winCEfile *) opaque)->handle;
|
||||
DWORD HighOrderPos;
|
||||
DWORD rc;
|
||||
|
||||
/* Get the high order 32-bits of the position */
|
||||
//HighOrderPos = HIGHORDER_UINT64(pos);
|
||||
HighOrderPos = (unsigned long)(pos>>32);
|
||||
|
||||
/*!!! SetFilePointer needs a signed 64-bit value. */
|
||||
/* Move pointer "pos" count from start of file */
|
||||
rc = SetFilePointer(Handle, (unsigned long)(pos&0x00000000ffffffff),
|
||||
&HighOrderPos, FILE_BEGIN);
|
||||
|
||||
if ((rc == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
|
||||
{
|
||||
BAIL_MACRO(win32strerror(), 0);
|
||||
}
|
||||
|
||||
return(1); /* No error occured */
|
||||
} /* __PHYSFS_platformSeek */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
|
||||
{
|
||||
HANDLE Handle = ((winCEfile *) opaque)->handle;
|
||||
DWORD HighPos = 0;
|
||||
DWORD LowPos;
|
||||
PHYSFS_sint64 retval;
|
||||
|
||||
/* Get current position */
|
||||
LowPos = SetFilePointer(Handle, 0, &HighPos, FILE_CURRENT);
|
||||
if ((LowPos == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
|
||||
{
|
||||
BAIL_MACRO(win32strerror(), 0);
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
/* Combine the high/low order to create the 64-bit position value */
|
||||
retval = (((PHYSFS_uint64) HighPos) << 32) | LowPos;
|
||||
//assert(retval >= 0);
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformTell */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
|
||||
{
|
||||
HANDLE Handle = ((winCEfile *) opaque)->handle;
|
||||
DWORD SizeHigh;
|
||||
DWORD SizeLow;
|
||||
PHYSFS_sint64 retval;
|
||||
|
||||
SizeLow = GetFileSize(Handle, &SizeHigh);
|
||||
if ((SizeLow == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
|
||||
{
|
||||
BAIL_MACRO(win32strerror(), -1);
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
/* Combine the high/low order to create the 64-bit position value */
|
||||
retval = (((PHYSFS_uint64) SizeHigh) << 32) | SizeLow;
|
||||
//assert(retval >= 0);
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformFileLength */
|
||||
|
||||
|
||||
int __PHYSFS_platformEOF(void *opaque)
|
||||
{
|
||||
PHYSFS_sint64 FilePosition;
|
||||
int retval = 0;
|
||||
|
||||
/* Get the current position in the file */
|
||||
if ((FilePosition = __PHYSFS_platformTell(opaque)) != 0)
|
||||
{
|
||||
/* Non-zero if EOF is equal to the file length */
|
||||
retval = FilePosition == __PHYSFS_platformFileLength(opaque);
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformEOF */
|
||||
|
||||
|
||||
int __PHYSFS_platformFlush(void *opaque)
|
||||
{
|
||||
winCEfile *fh = ((winCEfile *) opaque);
|
||||
if (!fh->readonly)
|
||||
BAIL_IF_MACRO(!FlushFileBuffers(fh->handle), win32strerror(), 0);
|
||||
|
||||
return(1);
|
||||
} /* __PHYSFS_platformFlush */
|
||||
|
||||
|
||||
int __PHYSFS_platformClose(void *opaque)
|
||||
{
|
||||
HANDLE Handle = ((winCEfile *) opaque)->handle;
|
||||
BAIL_IF_MACRO(!CloseHandle(Handle), win32strerror(), 0);
|
||||
allocator.Free(opaque);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformClose */
|
||||
|
||||
|
||||
int __PHYSFS_platformDelete(const char *path)
|
||||
{
|
||||
wchar_t *w_path = NULL;
|
||||
UTF8_TO_UNICODE_STACK_MACRO(w_path, path);
|
||||
|
||||
/* If filename is a folder */
|
||||
if (GetFileAttributes(w_path) == FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
int retval = !RemoveDirectory(w_path);
|
||||
__PHYSFS_smallFree(w_path);
|
||||
BAIL_IF_MACRO(retval, win32strerror(), 0);
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
int retval = !DeleteFile(w_path);
|
||||
__PHYSFS_smallFree(w_path);
|
||||
BAIL_IF_MACRO(retval, win32strerror(), 0);
|
||||
} /* else */
|
||||
|
||||
return(1); /* if you got here, it worked. */
|
||||
} /* __PHYSFS_platformDelete */
|
||||
|
||||
|
||||
/*
|
||||
* !!! FIXME: why aren't we using Critical Sections instead of Mutexes?
|
||||
* !!! FIXME: mutexes on Windows are for cross-process sync. CritSects are
|
||||
* !!! FIXME: mutexes for threads in a single process and are faster.
|
||||
*/
|
||||
void *__PHYSFS_platformCreateMutex(void)
|
||||
{
|
||||
return((void *) CreateMutex(NULL, FALSE, NULL));
|
||||
} /* __PHYSFS_platformCreateMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformDestroyMutex(void *mutex)
|
||||
{
|
||||
CloseHandle((HANDLE) mutex);
|
||||
} /* __PHYSFS_platformDestroyMutex */
|
||||
|
||||
|
||||
int __PHYSFS_platformGrabMutex(void *mutex)
|
||||
{
|
||||
return(WaitForSingleObject((HANDLE) mutex, INFINITE) != WAIT_FAILED);
|
||||
} /* __PHYSFS_platformGrabMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex)
|
||||
{
|
||||
ReleaseMutex((HANDLE) mutex);
|
||||
} /* __PHYSFS_platformReleaseMutex */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
|
||||
} /* __PHYSFS_platformGetLastModTime */
|
||||
|
||||
|
||||
/* !!! FIXME: Don't use C runtime for allocators? */
|
||||
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
|
||||
{
|
||||
return(0); /* just use malloc() and friends. */
|
||||
} /* __PHYSFS_platformSetDefaultAllocator */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_POCKETPC */
|
||||
|
||||
/* end of pocketpc.c ... */
|
||||
|
||||
424
project/jni/physfs/platform/posix.c
Normal file
424
project/jni/physfs/platform/posix.c
Normal file
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Posix-esque support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_platforms.h"
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_POSIX
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef PHYSFS_HAVE_LLSEEK
|
||||
#include <linux/unistd.h>
|
||||
#endif
|
||||
|
||||
#include "physfs_internal.h"
|
||||
|
||||
|
||||
const char *__PHYSFS_platformDirSeparator = "/";
|
||||
|
||||
|
||||
char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname)
|
||||
{
|
||||
const char *envr = getenv(varname);
|
||||
char *retval = NULL;
|
||||
|
||||
if (envr != NULL)
|
||||
{
|
||||
retval = (char *) allocator.Malloc(strlen(envr) + 1);
|
||||
if (retval != NULL)
|
||||
strcpy(retval, envr);
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformCopyEnvironmentVariable */
|
||||
|
||||
|
||||
static char *getUserNameByUID(void)
|
||||
{
|
||||
uid_t uid = getuid();
|
||||
struct passwd *pw;
|
||||
char *retval = NULL;
|
||||
|
||||
pw = getpwuid(uid);
|
||||
if ((pw != NULL) && (pw->pw_name != NULL))
|
||||
{
|
||||
retval = (char *) allocator.Malloc(strlen(pw->pw_name) + 1);
|
||||
if (retval != NULL)
|
||||
strcpy(retval, pw->pw_name);
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* getUserNameByUID */
|
||||
|
||||
|
||||
static char *getUserDirByUID(void)
|
||||
{
|
||||
uid_t uid = getuid();
|
||||
struct passwd *pw;
|
||||
char *retval = NULL;
|
||||
|
||||
pw = getpwuid(uid);
|
||||
if ((pw != NULL) && (pw->pw_dir != NULL))
|
||||
{
|
||||
retval = (char *) allocator.Malloc(strlen(pw->pw_dir) + 1);
|
||||
if (retval != NULL)
|
||||
strcpy(retval, pw->pw_dir);
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* getUserDirByUID */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserName(void)
|
||||
{
|
||||
char *retval = getUserNameByUID();
|
||||
if (retval == NULL)
|
||||
retval = __PHYSFS_platformCopyEnvironmentVariable("USER");
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformGetUserName */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserDir(void)
|
||||
{
|
||||
char *retval = __PHYSFS_platformCopyEnvironmentVariable("HOME");
|
||||
|
||||
/* if the environment variable was set, make sure it's really a dir. */
|
||||
if (retval != NULL)
|
||||
{
|
||||
struct stat statbuf;
|
||||
if ((stat(retval, &statbuf) == -1) || (S_ISDIR(statbuf.st_mode) == 0))
|
||||
{
|
||||
allocator.Free(retval);
|
||||
retval = NULL;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
if (retval == NULL)
|
||||
retval = getUserDirByUID();
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformGetUserDir */
|
||||
|
||||
|
||||
int __PHYSFS_platformExists(const char *fname)
|
||||
{
|
||||
struct stat statbuf;
|
||||
BAIL_IF_MACRO(lstat(fname, &statbuf) == -1, strerror(errno), 0);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformExists */
|
||||
|
||||
|
||||
int __PHYSFS_platformIsSymLink(const char *fname)
|
||||
{
|
||||
struct stat statbuf;
|
||||
BAIL_IF_MACRO(lstat(fname, &statbuf) == -1, strerror(errno), 0);
|
||||
return( (S_ISLNK(statbuf.st_mode)) ? 1 : 0 );
|
||||
} /* __PHYSFS_platformIsSymlink */
|
||||
|
||||
|
||||
int __PHYSFS_platformIsDirectory(const char *fname)
|
||||
{
|
||||
struct stat statbuf;
|
||||
BAIL_IF_MACRO(stat(fname, &statbuf) == -1, strerror(errno), 0);
|
||||
return( (S_ISDIR(statbuf.st_mode)) ? 1 : 0 );
|
||||
} /* __PHYSFS_platformIsDirectory */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCvtToDependent(const char *prepend,
|
||||
const char *dirName,
|
||||
const char *append)
|
||||
{
|
||||
int len = ((prepend) ? strlen(prepend) : 0) +
|
||||
((append) ? strlen(append) : 0) +
|
||||
strlen(dirName) + 1;
|
||||
char *retval = (char *) allocator.Malloc(len);
|
||||
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
/* platform-independent notation is Unix-style already. :) */
|
||||
|
||||
if (prepend)
|
||||
strcpy(retval, prepend);
|
||||
else
|
||||
retval[0] = '\0';
|
||||
|
||||
strcat(retval, dirName);
|
||||
|
||||
if (append)
|
||||
strcat(retval, append);
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformCvtToDependent */
|
||||
|
||||
|
||||
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_EnumFilesCallback callback,
|
||||
const char *origdir,
|
||||
void *callbackdata)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
int bufsize = 0;
|
||||
char *buf = NULL;
|
||||
int dlen = 0;
|
||||
|
||||
if (omitSymLinks) /* !!! FIXME: this malloc sucks. */
|
||||
{
|
||||
dlen = strlen(dirname);
|
||||
bufsize = dlen + 256;
|
||||
buf = (char *) allocator.Malloc(bufsize);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
strcpy(buf, dirname);
|
||||
if (buf[dlen - 1] != '/')
|
||||
{
|
||||
buf[dlen++] = '/';
|
||||
buf[dlen] = '\0';
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
errno = 0;
|
||||
dir = opendir(dirname);
|
||||
if (dir == NULL)
|
||||
{
|
||||
allocator.Free(buf);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
while ((ent = readdir(dir)) != NULL)
|
||||
{
|
||||
if (strcmp(ent->d_name, ".") == 0)
|
||||
continue;
|
||||
|
||||
if (strcmp(ent->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
if (omitSymLinks)
|
||||
{
|
||||
char *p;
|
||||
int len = strlen(ent->d_name) + dlen + 1;
|
||||
if (len > bufsize)
|
||||
{
|
||||
p = (char *) allocator.Realloc(buf, len);
|
||||
if (p == NULL)
|
||||
continue;
|
||||
buf = p;
|
||||
bufsize = len;
|
||||
} /* if */
|
||||
|
||||
strcpy(buf + dlen, ent->d_name);
|
||||
if (__PHYSFS_platformIsSymLink(buf))
|
||||
continue;
|
||||
} /* if */
|
||||
|
||||
callback(callbackdata, origdir, ent->d_name);
|
||||
} /* while */
|
||||
|
||||
allocator.Free(buf);
|
||||
closedir(dir);
|
||||
} /* __PHYSFS_platformEnumerateFiles */
|
||||
|
||||
|
||||
int __PHYSFS_platformMkDir(const char *path)
|
||||
{
|
||||
int rc;
|
||||
errno = 0;
|
||||
rc = mkdir(path, S_IRWXU);
|
||||
BAIL_IF_MACRO(rc == -1, strerror(errno), 0);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformMkDir */
|
||||
|
||||
|
||||
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);
|
||||
BAIL_IF_MACRO(fd < 0, strerror(errno), NULL);
|
||||
|
||||
if (appending)
|
||||
{
|
||||
if (lseek(fd, 0, SEEK_END) < 0)
|
||||
{
|
||||
close(fd);
|
||||
BAIL_MACRO(strerror(errno), NULL);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
retval = (int *) allocator.Malloc(sizeof (int));
|
||||
if (retval == NULL)
|
||||
{
|
||||
close(fd);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
} /* if */
|
||||
|
||||
*retval = fd;
|
||||
return((void *) retval);
|
||||
} /* doOpen */
|
||||
|
||||
|
||||
void *__PHYSFS_platformOpenRead(const char *filename)
|
||||
{
|
||||
return(doOpen(filename, O_RDONLY));
|
||||
} /* __PHYSFS_platformOpenRead */
|
||||
|
||||
|
||||
void *__PHYSFS_platformOpenWrite(const char *filename)
|
||||
{
|
||||
return(doOpen(filename, O_WRONLY | O_CREAT | O_TRUNC));
|
||||
} /* __PHYSFS_platformOpenWrite */
|
||||
|
||||
|
||||
void *__PHYSFS_platformOpenAppend(const char *filename)
|
||||
{
|
||||
return(doOpen(filename, O_WRONLY | O_CREAT | O_APPEND));
|
||||
} /* __PHYSFS_platformOpenAppend */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
|
||||
PHYSFS_uint32 size, PHYSFS_uint32 count)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
int max = size * count;
|
||||
int rc = read(fd, buffer, max);
|
||||
|
||||
BAIL_IF_MACRO(rc == -1, strerror(errno), rc);
|
||||
assert(rc <= max);
|
||||
|
||||
if ((rc < max) && (size > 1))
|
||||
lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */
|
||||
|
||||
return(rc / size);
|
||||
} /* __PHYSFS_platformRead */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
|
||||
PHYSFS_uint32 size, PHYSFS_uint32 count)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
int max = size * count;
|
||||
int rc = write(fd, (void *) buffer, max);
|
||||
|
||||
BAIL_IF_MACRO(rc == -1, strerror(errno), rc);
|
||||
assert(rc <= max);
|
||||
|
||||
if ((rc < max) && (size > 1))
|
||||
lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */
|
||||
|
||||
return(rc / size);
|
||||
} /* __PHYSFS_platformWrite */
|
||||
|
||||
|
||||
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
|
||||
#ifdef PHYSFS_HAVE_LLSEEK
|
||||
unsigned long offset_high = ((pos >> 32) & 0xFFFFFFFF);
|
||||
unsigned long offset_low = (pos & 0xFFFFFFFF);
|
||||
loff_t retoffset;
|
||||
int rc = llseek(fd, offset_high, offset_low, &retoffset, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc == -1, strerror(errno), 0);
|
||||
#else
|
||||
BAIL_IF_MACRO(lseek(fd, (int) pos, SEEK_SET) == -1, strerror(errno), 0);
|
||||
#endif
|
||||
|
||||
return(1);
|
||||
} /* __PHYSFS_platformSeek */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
PHYSFS_sint64 retval;
|
||||
|
||||
#ifdef PHYSFS_HAVE_LLSEEK
|
||||
loff_t retoffset;
|
||||
int rc = llseek(fd, 0, &retoffset, SEEK_CUR);
|
||||
BAIL_IF_MACRO(rc == -1, strerror(errno), -1);
|
||||
retval = (PHYSFS_sint64) retoffset;
|
||||
#else
|
||||
retval = (PHYSFS_sint64) lseek(fd, 0, SEEK_CUR);
|
||||
BAIL_IF_MACRO(retval == -1, strerror(errno), -1);
|
||||
#endif
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformTell */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
struct stat statbuf;
|
||||
BAIL_IF_MACRO(fstat(fd, &statbuf) == -1, strerror(errno), -1);
|
||||
return((PHYSFS_sint64) statbuf.st_size);
|
||||
} /* __PHYSFS_platformFileLength */
|
||||
|
||||
|
||||
int __PHYSFS_platformEOF(void *opaque)
|
||||
{
|
||||
PHYSFS_sint64 pos = __PHYSFS_platformTell(opaque);
|
||||
PHYSFS_sint64 len = __PHYSFS_platformFileLength(opaque);
|
||||
return(pos >= len);
|
||||
} /* __PHYSFS_platformEOF */
|
||||
|
||||
|
||||
int __PHYSFS_platformFlush(void *opaque)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
BAIL_IF_MACRO(fsync(fd) == -1, strerror(errno), 0);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformFlush */
|
||||
|
||||
|
||||
int __PHYSFS_platformClose(void *opaque)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
BAIL_IF_MACRO(close(fd) == -1, strerror(errno), 0);
|
||||
allocator.Free(opaque);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformClose */
|
||||
|
||||
|
||||
int __PHYSFS_platformDelete(const char *path)
|
||||
{
|
||||
BAIL_IF_MACRO(remove(path) == -1, strerror(errno), 0);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformDelete */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
|
||||
{
|
||||
struct stat statbuf;
|
||||
BAIL_IF_MACRO(stat(fname, &statbuf) < 0, strerror(errno), -1);
|
||||
return statbuf.st_mtime;
|
||||
} /* __PHYSFS_platformGetLastModTime */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_POSIX */
|
||||
|
||||
/* end of posix.c ... */
|
||||
|
||||
446
project/jni/physfs/platform/unix.c
Normal file
446
project/jni/physfs/platform/unix.c
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Unix support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_platforms.h"
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_UNIX
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if (!defined PHYSFS_NO_THREAD_SUPPORT)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef PHYSFS_HAVE_SYS_UCRED_H
|
||||
# ifdef PHYSFS_HAVE_MNTENT_H
|
||||
# undef PHYSFS_HAVE_MNTENT_H /* don't do both... */
|
||||
# endif
|
||||
# include <sys/ucred.h>
|
||||
# include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#ifdef PHYSFS_HAVE_MNTENT_H
|
||||
#include <mntent.h>
|
||||
#endif
|
||||
|
||||
#include "physfs_internal.h"
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN 1024
|
||||
#endif
|
||||
|
||||
int __PHYSFS_platformInit(void)
|
||||
{
|
||||
return(1); /* always succeed. */
|
||||
} /* __PHYSFS_platformInit */
|
||||
|
||||
|
||||
int __PHYSFS_platformDeinit(void)
|
||||
{
|
||||
return(1); /* always succeed. */
|
||||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
#ifdef PHYSFS_NO_CDROM_SUPPORT
|
||||
|
||||
/* Stub version for platforms without CD-ROM support. */
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
#elif (defined PHYSFS_HAVE_SYS_UCRED_H)
|
||||
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
int i;
|
||||
struct statfs *mntbufp = NULL;
|
||||
int mounts = getmntinfo(&mntbufp, MNT_WAIT);
|
||||
|
||||
for (i = 0; i < mounts; i++)
|
||||
{
|
||||
int add_it = 0;
|
||||
|
||||
if (strcmp(mntbufp[i].f_fstypename, "iso9660") == 0)
|
||||
add_it = 1;
|
||||
else if (strcmp( mntbufp[i].f_fstypename, "cd9660") == 0)
|
||||
add_it = 1;
|
||||
|
||||
/* add other mount types here */
|
||||
|
||||
if (add_it)
|
||||
cb(data, mntbufp[i].f_mntonname);
|
||||
} /* for */
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
#elif (defined PHYSFS_HAVE_MNTENT_H)
|
||||
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
FILE *mounts = NULL;
|
||||
struct mntent *ent = NULL;
|
||||
|
||||
mounts = setmntent("/etc/mtab", "r");
|
||||
BAIL_IF_MACRO(mounts == NULL, ERR_IO_ERROR, /*return void*/);
|
||||
|
||||
while ( (ent = getmntent(mounts)) != NULL )
|
||||
{
|
||||
int add_it = 0;
|
||||
if (strcmp(ent->mnt_type, "iso9660") == 0)
|
||||
add_it = 1;
|
||||
else if (strcmp(ent->mnt_type, "udf") == 0)
|
||||
add_it = 1;
|
||||
|
||||
/* !!! FIXME: these might pick up floppy drives, right? */
|
||||
else if (strcmp(ent->mnt_type, "auto") == 0)
|
||||
add_it = 1;
|
||||
else if (strcmp(ent->mnt_type, "supermount") == 0)
|
||||
add_it = 1;
|
||||
|
||||
/* add other mount types here */
|
||||
|
||||
if (add_it)
|
||||
cb(data, ent->mnt_dir);
|
||||
} /* while */
|
||||
|
||||
endmntent(mounts);
|
||||
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* this is in posix.c ... */
|
||||
extern char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname);
|
||||
|
||||
|
||||
/*
|
||||
* See where program (bin) resides in the $PATH specified by (envr).
|
||||
* returns a copy of the first element in envr that contains it, or NULL
|
||||
* if it doesn't exist or there were other problems. PHYSFS_SetError() is
|
||||
* called if we have a problem.
|
||||
*
|
||||
* (envr) will be scribbled over, and you are expected to allocator.Free() the
|
||||
* return value when you're done with it.
|
||||
*/
|
||||
static char *findBinaryInPath(const char *bin, char *envr)
|
||||
{
|
||||
size_t alloc_size = 0;
|
||||
char *exe = NULL;
|
||||
char *start = envr;
|
||||
char *ptr;
|
||||
|
||||
BAIL_IF_MACRO(bin == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||
BAIL_IF_MACRO(envr == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||
|
||||
do
|
||||
{
|
||||
size_t size;
|
||||
ptr = strchr(start, ':'); /* find next $PATH separator. */
|
||||
if (ptr)
|
||||
*ptr = '\0';
|
||||
|
||||
size = strlen(start) + strlen(bin) + 2;
|
||||
if (size > alloc_size)
|
||||
{
|
||||
char *x = (char *) allocator.Realloc(exe, size);
|
||||
if (x == NULL)
|
||||
{
|
||||
if (exe != NULL)
|
||||
allocator.Free(exe);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
} /* if */
|
||||
|
||||
alloc_size = size;
|
||||
exe = x;
|
||||
} /* if */
|
||||
|
||||
/* build full binary path... */
|
||||
strcpy(exe, start);
|
||||
if ((exe[0] == '\0') || (exe[strlen(exe) - 1] != '/'))
|
||||
strcat(exe, "/");
|
||||
strcat(exe, bin);
|
||||
|
||||
if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */
|
||||
{
|
||||
strcpy(exe, start); /* i'm lazy. piss off. */
|
||||
return(exe);
|
||||
} /* if */
|
||||
|
||||
start = ptr + 1; /* start points to beginning of next element. */
|
||||
} while (ptr != NULL);
|
||||
|
||||
if (exe != NULL)
|
||||
allocator.Free(exe);
|
||||
|
||||
return(NULL); /* doesn't exist in path. */
|
||||
} /* findBinaryInPath */
|
||||
|
||||
|
||||
static char *readSymLink(const char *path)
|
||||
{
|
||||
ssize_t len = 64;
|
||||
ssize_t rc = -1;
|
||||
char *retval = NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *ptr = (char *) allocator.Realloc(retval, (size_t) len);
|
||||
if (ptr == NULL)
|
||||
break; /* out of memory. */
|
||||
retval = ptr;
|
||||
|
||||
rc = readlink(path, retval, len);
|
||||
if (rc == -1)
|
||||
break; /* not a symlink, i/o error, etc. */
|
||||
|
||||
else if (rc < len)
|
||||
{
|
||||
retval[rc] = '\0'; /* readlink doesn't null-terminate. */
|
||||
return retval; /* we're good to go. */
|
||||
} /* else if */
|
||||
|
||||
len *= 2; /* grow buffer, try again. */
|
||||
} /* while */
|
||||
|
||||
if (retval != NULL)
|
||||
allocator.Free(retval);
|
||||
return NULL;
|
||||
} /* readSymLink */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
{
|
||||
char *retval = NULL;
|
||||
char *envr = NULL;
|
||||
|
||||
/* fast path: default behaviour can handle this. */
|
||||
if ( (argv0 != NULL) && (strchr(argv0, '/') != NULL) )
|
||||
return(NULL); /* higher level will parse out real path from argv0. */
|
||||
|
||||
/*
|
||||
* Try to avoid using argv0 unless forced to. If there's a Linux-like
|
||||
* /proc filesystem, you can get the full path to the current process from
|
||||
* the /proc/self/exe symlink.
|
||||
*/
|
||||
retval = readSymLink("/proc/self/exe");
|
||||
if (retval == NULL)
|
||||
{
|
||||
/* older kernels don't have /proc/self ... try PID version... */
|
||||
const unsigned long long pid = (unsigned long long) getpid();
|
||||
char path[64];
|
||||
const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid);
|
||||
if ( (rc > 0) && (rc < sizeof(path)) )
|
||||
retval = readSymLink(path);
|
||||
} /* if */
|
||||
|
||||
if (retval != NULL) /* chop off filename. */
|
||||
{
|
||||
char *ptr = strrchr(retval, '/');
|
||||
if (ptr != NULL)
|
||||
*ptr = '\0';
|
||||
} /* if */
|
||||
|
||||
if ((retval == NULL) && (argv0 != NULL))
|
||||
{
|
||||
/* If there's no dirsep on argv0, then look through $PATH for it. */
|
||||
envr = __PHYSFS_platformCopyEnvironmentVariable("PATH");
|
||||
BAIL_IF_MACRO(!envr, NULL, NULL);
|
||||
retval = findBinaryInPath(argv0, envr);
|
||||
allocator.Free(envr);
|
||||
} /* if */
|
||||
|
||||
if (retval != NULL)
|
||||
{
|
||||
/* try to shrink buffer... */
|
||||
char *ptr = (char *) allocator.Realloc(retval, strlen(retval) + 1);
|
||||
if (ptr != NULL)
|
||||
retval = ptr; /* oh well if it failed. */
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformCalcBaseDir */
|
||||
|
||||
|
||||
char *__PHYSFS_platformRealPath(const char *path)
|
||||
{
|
||||
char resolved_path[MAXPATHLEN];
|
||||
char *retval = NULL;
|
||||
|
||||
errno = 0;
|
||||
BAIL_IF_MACRO(!realpath(path, resolved_path), strerror(errno), NULL);
|
||||
retval = (char *) allocator.Malloc(strlen(resolved_path) + 1);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
strcpy(retval, resolved_path);
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformRealPath */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCurrentDir(void)
|
||||
{
|
||||
/*
|
||||
* This can't just do platformRealPath("."), since that would eventually
|
||||
* just end up calling back into here.
|
||||
*/
|
||||
|
||||
int allocSize = 0;
|
||||
char *retval = NULL;
|
||||
char *ptr;
|
||||
|
||||
do
|
||||
{
|
||||
allocSize += 100;
|
||||
ptr = (char *) allocator.Realloc(retval, allocSize);
|
||||
if (ptr == NULL)
|
||||
{
|
||||
if (retval != NULL)
|
||||
allocator.Free(retval);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
} /* if */
|
||||
|
||||
retval = ptr;
|
||||
ptr = getcwd(retval, allocSize);
|
||||
} while (ptr == NULL && errno == ERANGE);
|
||||
|
||||
if (ptr == NULL && errno)
|
||||
{
|
||||
/*
|
||||
* getcwd() failed for some reason, for example current
|
||||
* directory not existing.
|
||||
*/
|
||||
if (retval != NULL)
|
||||
allocator.Free(retval);
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformCurrentDir */
|
||||
|
||||
|
||||
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
|
||||
{
|
||||
return(0); /* just use malloc() and friends. */
|
||||
} /* __PHYSFS_platformSetDefaultAllocator */
|
||||
|
||||
|
||||
#if (defined PHYSFS_NO_THREAD_SUPPORT)
|
||||
|
||||
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void) { return(0x0001); }
|
||||
void *__PHYSFS_platformCreateMutex(void) { return((void *) 0x0001); }
|
||||
void __PHYSFS_platformDestroyMutex(void *mutex) {}
|
||||
int __PHYSFS_platformGrabMutex(void *mutex) { return(1); }
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex) {}
|
||||
|
||||
#else
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
pthread_t owner;
|
||||
PHYSFS_uint32 count;
|
||||
} PthreadMutex;
|
||||
|
||||
/* Just in case; this is a panic value. */
|
||||
#if ((!defined SIZEOF_INT) || (SIZEOF_INT <= 0))
|
||||
# define SIZEOF_INT 4
|
||||
#endif
|
||||
|
||||
#if (SIZEOF_INT == 4)
|
||||
# define PHTREAD_TO_UI64(thr) ( (PHYSFS_uint64) ((PHYSFS_uint32) (thr)) )
|
||||
#elif (SIZEOF_INT == 2)
|
||||
# define PHTREAD_TO_UI64(thr) ( (PHYSFS_uint64) ((PHYSFS_uint16) (thr)) )
|
||||
#elif (SIZEOF_INT == 1)
|
||||
# define PHTREAD_TO_UI64(thr) ( (PHYSFS_uint64) ((PHYSFS_uint8) (thr)) )
|
||||
#else
|
||||
# define PHTREAD_TO_UI64(thr) ((PHYSFS_uint64) (thr))
|
||||
#endif
|
||||
|
||||
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return(PHTREAD_TO_UI64(pthread_self()));
|
||||
} /* __PHYSFS_platformGetThreadID */
|
||||
|
||||
|
||||
void *__PHYSFS_platformCreateMutex(void)
|
||||
{
|
||||
int rc;
|
||||
PthreadMutex *m = (PthreadMutex *) allocator.Malloc(sizeof (PthreadMutex));
|
||||
BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
rc = pthread_mutex_init(&m->mutex, NULL);
|
||||
if (rc != 0)
|
||||
{
|
||||
allocator.Free(m);
|
||||
BAIL_MACRO(strerror(rc), NULL);
|
||||
} /* if */
|
||||
|
||||
m->count = 0;
|
||||
m->owner = (pthread_t) 0xDEADBEEF;
|
||||
return((void *) m);
|
||||
} /* __PHYSFS_platformCreateMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformDestroyMutex(void *mutex)
|
||||
{
|
||||
PthreadMutex *m = (PthreadMutex *) mutex;
|
||||
|
||||
/* Destroying a locked mutex is a bug, but we'll try to be helpful. */
|
||||
if ((m->owner == pthread_self()) && (m->count > 0))
|
||||
pthread_mutex_unlock(&m->mutex);
|
||||
|
||||
pthread_mutex_destroy(&m->mutex);
|
||||
allocator.Free(m);
|
||||
} /* __PHYSFS_platformDestroyMutex */
|
||||
|
||||
|
||||
int __PHYSFS_platformGrabMutex(void *mutex)
|
||||
{
|
||||
PthreadMutex *m = (PthreadMutex *) mutex;
|
||||
pthread_t tid = pthread_self();
|
||||
if (m->owner != tid)
|
||||
{
|
||||
if (pthread_mutex_lock(&m->mutex) != 0)
|
||||
return(0);
|
||||
m->owner = tid;
|
||||
} /* if */
|
||||
|
||||
m->count++;
|
||||
return(1);
|
||||
} /* __PHYSFS_platformGrabMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex)
|
||||
{
|
||||
PthreadMutex *m = (PthreadMutex *) mutex;
|
||||
if (m->owner == pthread_self())
|
||||
{
|
||||
if (--m->count == 0)
|
||||
{
|
||||
m->owner = (pthread_t) 0xDEADBEEF;
|
||||
pthread_mutex_unlock(&m->mutex);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* __PHYSFS_platformReleaseMutex */
|
||||
|
||||
#endif /* !PHYSFS_NO_THREAD_SUPPORT */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_UNIX */
|
||||
|
||||
/* end of unix.c ... */
|
||||
|
||||
1403
project/jni/physfs/platform/windows.c
Normal file
1403
project/jni/physfs/platform/windows.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user