awesome!!!
This commit is contained in:
11
third-party/physfs/extras/README-CSharp.txt
vendored
Normal file
11
third-party/physfs/extras/README-CSharp.txt
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
There used to be C# bindings in this directory, but they have been
|
||||
unmaintained for many years.
|
||||
|
||||
Instead, there is a more modern PhysicsFS wrapper for .NET available.
|
||||
|
||||
You can find it at https://github.com/frabert/SharpPhysFS
|
||||
|
||||
Thanks to Francesco Bertolaccini for his efforts on that project!
|
||||
|
||||
--ryan.
|
||||
|
165
third-party/physfs/extras/abs-file.h
vendored
Normal file
165
third-party/physfs/extras/abs-file.h
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* stdio/physfs abstraction layer 2003-04-02
|
||||
*
|
||||
* Adam D. Moss <adam@gimp.org> <aspirin@icculus.org>
|
||||
*
|
||||
* These wrapper macros and functions are designed to allow a program
|
||||
* to perform file I/O with identical semantics and syntax regardless
|
||||
* of whether PhysicsFS is being used or not.
|
||||
*/
|
||||
#ifndef _ABS_FILE_H
|
||||
#define _ABS_FILE_H
|
||||
/*
|
||||
PLEASE NOTE: This license applies to abs-file.h ONLY (to make it clear that
|
||||
you may embed this wrapper code within commercial software); PhysicsFS itself
|
||||
is (at the time of writing) released under a different license with
|
||||
additional restrictions.
|
||||
|
||||
Copyright (C) 2002-2003 Adam D. Moss (the "Author"). All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is fur-
|
||||
nished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
|
||||
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
|
||||
NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of the Author of the
|
||||
Software shall not be used in advertising or otherwise to promote the sale,
|
||||
use or other dealings in this Software without prior written authorization
|
||||
from the Author.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* API:
|
||||
*
|
||||
* Macro/function use like stdio equivalent...
|
||||
* -------------- ----------------------------
|
||||
* MY_FILETYPE FILE
|
||||
* MY_OPEN_FOR_READ fopen(..., "rb")
|
||||
* MY_READ fread(...)
|
||||
* MY_CLOSE fclose(...)
|
||||
* MY_GETC fgetc(...)
|
||||
* MY_GETS fgets(...)
|
||||
* MY_ATEOF feof(...)
|
||||
* MY_TELL ftell(...)
|
||||
* MY_SEEK fseek(..., SEEK_SET)
|
||||
* MY_REWIND rewind(...)
|
||||
* MY_SETBUFFER (not a standard for stdio, does nothing there)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Important DEFINEs:
|
||||
* It is important to define these consistantly across the various
|
||||
* compilation modules of your program if you wish to exchange file
|
||||
* handles between them.
|
||||
*
|
||||
* USE_PHYSFS: Define USE_PHYSFS if PhysicsFS is being used; note that if
|
||||
* you do intend to use PhysicsFS then you will still need to initialize
|
||||
* PhysicsFS yourself and set up its search-paths.
|
||||
*
|
||||
* Optional DEFINEs:
|
||||
*
|
||||
* PHYSFS_DEFAULT_READ_BUFFER <bytes>: If set then abs-file.h sets the
|
||||
* PhysicsFS buffer size to this value whenever you open a file. You
|
||||
* may over-ride this on a per-filehandle basis by using the
|
||||
* MY_SETBUFFER() macro (which simply does nothing when not using
|
||||
* PhysicsFS). If you have not defined this value explicitly then
|
||||
* abs-file.h will default to the same default buffer size as used by
|
||||
* stdio if it can be determined, or 8192 bytes otherwise.
|
||||
*/
|
||||
#ifndef PHYSFS_DEFAULT_READ_BUFFER
|
||||
#ifdef BUFSIZ
|
||||
#define PHYSFS_DEFAULT_READ_BUFFER BUFSIZ
|
||||
#else
|
||||
#define PHYSFS_DEFAULT_READ_BUFFER 8192
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_PHYSFS
|
||||
|
||||
#include <physfs.h>
|
||||
#define MY_FILETYPE PHYSFS_File
|
||||
#define MY_SETBUFFER(fp,size) PHYSFS_setBuffer(fp,size)
|
||||
#define MY_READ(p,s,n,fp) PHYSFS_read(fp,p,s,n)
|
||||
#if PHYSFS_DEFAULT_READ_BUFFER
|
||||
static MY_FILETYPE* MY_OPEN_FOR_READ(const char *const filename)
|
||||
{
|
||||
MY_FILETYPE *const file = PHYSFS_openRead(filename);
|
||||
if (file) {
|
||||
MY_SETBUFFER(file, PHYSFS_DEFAULT_READ_BUFFER);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
#else
|
||||
#define MY_OPEN_FOR_READ(fn) PHYSFS_openRead(fn)
|
||||
#endif
|
||||
static int MY_GETC(MY_FILETYPE *const fp) {
|
||||
unsigned char c;
|
||||
/*if (PHYSFS_eof(fp)) {
|
||||
return EOF;
|
||||
}
|
||||
MY_READ(&c, 1, 1, fp);*/
|
||||
if (MY_READ(&c, 1, 1, fp) != 1) {
|
||||
return EOF;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
static char * MY_GETS(char * const str, const int size,
|
||||
MY_FILETYPE *const fp) {
|
||||
int i = 0;
|
||||
int c;
|
||||
do {
|
||||
if (i == size-1) {
|
||||
break;
|
||||
}
|
||||
c = MY_GETC(fp);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
str[i++] = c;
|
||||
} while (c != '\0' &&
|
||||
c != -1 &&
|
||||
c != '\n');
|
||||
str[i] = '\0';
|
||||
if (i == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
#define MY_CLOSE(fp) PHYSFS_close(fp)
|
||||
#define MY_ATEOF(fp) PHYSFS_eof(fp)
|
||||
#define MY_TELL(fp) PHYSFS_tell(fp)
|
||||
#define MY_SEEK(fp,o) PHYSFS_seek(fp,o)
|
||||
#define MY_REWIND(fp) MY_SEEK(fp,0)
|
||||
|
||||
#else
|
||||
|
||||
#define MY_FILETYPE FILE
|
||||
#define MY_READ(p,s,n,fp) fread(p,s,n,fp)
|
||||
#define MY_OPEN_FOR_READ(n) fopen(n, "rb")
|
||||
#define MY_GETC(fp) fgetc(fp)
|
||||
#define MY_GETS(str,size,fp) fgets(str,size,fp)
|
||||
#define MY_CLOSE(fp) fclose(fp)
|
||||
#define MY_ATEOF(fp) feof(fp)
|
||||
#define MY_TELL(fp) ftell(fp)
|
||||
#define MY_SEEK(fp,o) fseek(fp,o, SEEK_SET)
|
||||
#define MY_REWIND(fp) rewind(fp)
|
||||
/*static void MY_SETBUFFER(const MY_FILETYPE *const file, const int num) { }*/
|
||||
#define MY_SETBUFFER(fp,size)
|
||||
#endif
|
||||
|
||||
#endif
|
59
third-party/physfs/extras/buildbot-checker.sh
vendored
Normal file
59
third-party/physfs/extras/buildbot-checker.sh
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This is a script used by some Buildbot workers to push the project
|
||||
# through Clang's static analyzer and prepare the output to be uploaded
|
||||
# back to the buildmaster. You might find it useful too.
|
||||
|
||||
# Install Clang (you already have it on Mac OS X, apt-get install clang
|
||||
# on Ubuntu, etc), Make sure "scan-build" is in your $PATH.
|
||||
|
||||
FINALDIR="$1"
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
cd `dirname "$0"`
|
||||
cd ..
|
||||
|
||||
rm -rf checker-buildbot analysis
|
||||
if [ ! -z "$FINALDIR" ]; then
|
||||
rm -rf "$FINALDIR"
|
||||
fi
|
||||
|
||||
mkdir checker-buildbot
|
||||
cd checker-buildbot
|
||||
|
||||
# We turn off deprecated declarations, because we don't care about these warnings during static analysis.
|
||||
# The -Wno-liblto is new since our checker-279 upgrade, I think; checker otherwise warns "libLTO.dylib relative to clang installed dir not found"
|
||||
|
||||
# You might want to do this for CMake-backed builds instead...
|
||||
scan-build -o analysis cmake -G Ninja -Wno-dev -DPHYSFS_BUILD_SHARED=False -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS="-Wno-deprecated-declarations" -DCMAKE_EXE_LINKER_FLAGS="-Wno-liblto" ..
|
||||
|
||||
rm -rf analysis
|
||||
scan-build -o analysis cmake --build . --config Debug
|
||||
|
||||
if [ `ls -A analysis |wc -l` == 0 ] ; then
|
||||
mkdir analysis/zarro
|
||||
echo '<html><head><title>Zarro boogs</title></head><body>Static analysis: no issues to report.</body></html>' >analysis/zarro/index.html
|
||||
fi
|
||||
|
||||
mv analysis/* ../analysis
|
||||
rmdir analysis # Make sure this is empty.
|
||||
cd ..
|
||||
chmod -R a+r analysis
|
||||
chmod -R go-w analysis
|
||||
find analysis -type d -exec chmod a+x {} \;
|
||||
if [ -x /usr/bin/xattr ]; then find analysis -exec /usr/bin/xattr -d com.apple.quarantine {} \; 2>/dev/null ; fi
|
||||
|
||||
if [ ! -z "$FINALDIR" ]; then
|
||||
mv analysis "$FINALDIR"
|
||||
else
|
||||
FINALDIR=analysis
|
||||
fi
|
||||
|
||||
rm -rf checker-buildbot
|
||||
|
||||
echo "Done. Final output is in '$FINALDIR' ..."
|
||||
|
||||
# end of checker-buildbot.sh ...
|
||||
|
52
third-party/physfs/extras/buildbot-emscripten.sh
vendored
Normal file
52
third-party/physfs/extras/buildbot-emscripten.sh
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z "$SDKDIR" ]; then
|
||||
SDKDIR="/emsdk"
|
||||
fi
|
||||
|
||||
ENVSCRIPT="$SDKDIR/emsdk_env.sh"
|
||||
if [ ! -f "$ENVSCRIPT" ]; then
|
||||
echo "ERROR: This script expects the Emscripten SDK to be in '$SDKDIR'." 1>&2
|
||||
echo "ERROR: Set the \$SDKDIR environment variable to override this." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARBALL="$1"
|
||||
if [ -z $1 ]; then
|
||||
TARBALL=physfs-emscripten.tar.xz
|
||||
fi
|
||||
|
||||
cd `dirname "$0"`
|
||||
cd ..
|
||||
PHYSFSBASE=`pwd`
|
||||
|
||||
echo "Setting up Emscripten SDK environment..."
|
||||
source "$ENVSCRIPT"
|
||||
|
||||
echo "Setting up..."
|
||||
cd "$PHYSFSBASE"
|
||||
rm -rf buildbot
|
||||
mkdir buildbot
|
||||
cd buildbot
|
||||
|
||||
echo "Configuring..."
|
||||
emcmake cmake -G "Ninja" -DPHYSFS_BUILD_SHARED=False -DCMAKE_BUILD_TYPE=MinSizeRel .. || exit $?
|
||||
|
||||
echo "Building..."
|
||||
emmake cmake --build . --config MinSizeRel || exit $?
|
||||
|
||||
set -e
|
||||
rm -rf "$TARBALL" physfs-emscripten
|
||||
mkdir -p physfs-emscripten
|
||||
echo "Archiving to '$TARBALL' ..."
|
||||
cp ../src/physfs.h libphysfs.a physfs-emscripten
|
||||
chmod -R a+r physfs-emscripten
|
||||
chmod a+x physfs-emscripten
|
||||
chmod -R go-w physfs-emscripten
|
||||
tar -cJvvf "$TARBALL" physfs-emscripten
|
||||
echo "Done."
|
||||
|
||||
exit 0
|
||||
|
||||
# end of emscripten-buildbot.sh ...
|
||||
|
87
third-party/physfs/extras/buildbot-os2.sh
vendored
Normal file
87
third-party/physfs/extras/buildbot-os2.sh
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This is used by the buildbot to cross-compile for OS/2 from Linux, using
|
||||
# OpenWatcom. In an ideal world, we wouldn't need this, but we need a few
|
||||
# things to do this "properly" ...
|
||||
#
|
||||
# - OS/2 running as a VMware guest on the build machine
|
||||
# - Buildbot-worker running on that OS/2 guest
|
||||
# - CMake for OS/2 that...
|
||||
# - ... has Open Watcom compiler support and...
|
||||
# - ... a Watcom WMake project generator.
|
||||
#
|
||||
# Some of these things are doable (there is a CMake port for OS/2, you can
|
||||
# use GCC with it), but since OpenWatcom will just target OS/2 on Linux just
|
||||
# like it could on OS/2, it's easier and more efficient to just have a
|
||||
# buildbot script compile it here.
|
||||
#
|
||||
# Note that we just blast all the C files through the wcc386 compiler and
|
||||
# skip CMake entirely. We should fix this at some point.
|
||||
|
||||
set -e
|
||||
|
||||
ZIPFILE="$1"
|
||||
if [ -z $ZIPFILE ]; then
|
||||
ZIPFILE=physfs-os2.zip
|
||||
fi
|
||||
|
||||
export WATCOM="/usr/local/share/watcom"
|
||||
export PATH="$PATH:$WATCOM/binl"
|
||||
|
||||
CFLAGS="-i=\"$WATCOM/h;$WATCOM/h/os2;../src\" -wx -d0 -otexan -6r -zq -bt=os2 -fo=.obj -mf"
|
||||
WLIBFLAGS="-b -c -n -q -p=512"
|
||||
|
||||
cd `dirname "$0"`
|
||||
cd ..
|
||||
mkdir -p buildbot
|
||||
cd buildbot
|
||||
|
||||
rm -f test_physfs.obj
|
||||
|
||||
OKAY="1"
|
||||
for src in ../src/*.c ; do
|
||||
echo wcc386 $src $CFLAGS
|
||||
wcc386 $src $CFLAGS || OKAY="0"
|
||||
done
|
||||
|
||||
if [ "$OKAY" == "1" ]; then
|
||||
echo wlib $WLIBFLAGS physfs.lib *.obj
|
||||
wlib $WLIBFLAGS physfs.lib *.obj || OKAY="0"
|
||||
fi
|
||||
|
||||
echo wcc386 ../test/test_physfs.c $CFLAGS
|
||||
wcc386 ../test/test_physfs.c $CFLAGS || OKAY="0"
|
||||
|
||||
if [ "$OKAY" == "1" ]; then
|
||||
LDFLAGS="name test_physfs d all sys os2v2 op m libr physfs op q op symf FIL test_physfs.obj"
|
||||
echo wlink $LDFLAGS
|
||||
wlink $LDFLAGS || OKAY="0"
|
||||
fi
|
||||
|
||||
if [ "$OKAY" == "1" ]; then
|
||||
F=`file test_physfs.exe`
|
||||
echo "$F"
|
||||
if [ "$F" != 'test_physfs.exe: MS-DOS executable, LX for OS/2 (console) i80386' ]; then
|
||||
echo 1>&2 "ERROR: final binary doesn't appear to be OS/2 executable."
|
||||
OKAY=0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$OKAY" == "1" ]; then
|
||||
echo 1>&2 "Build succeeded."
|
||||
set -e
|
||||
rm -rf "$ZIPFILE" physfs-os2
|
||||
mkdir -p physfs-os2
|
||||
echo "Zipping to '$ZIPFILE' ..."
|
||||
cp ../src/physfs.h physfs.lib physfs-os2
|
||||
chmod -R a+r physfs-os2
|
||||
chmod a+x physfs-os2
|
||||
chmod -R go-w physfs-os2
|
||||
zip -9r "$ZIPFILE" physfs-os2
|
||||
echo "Done."
|
||||
exit 0
|
||||
else
|
||||
echo 1>&2 "Build failed."
|
||||
exit 1
|
||||
fi
|
||||
|
56
third-party/physfs/extras/buildbot-raspberrypi.sh
vendored
Normal file
56
third-party/physfs/extras/buildbot-raspberrypi.sh
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This is the script physfs-buildbot.icculus.org uses to cross-compile
|
||||
# PhysicsFS from x86 Linux to Raspberry Pi. This script was originally from
|
||||
# Simple Directmedia Layer ( https://www.libsdl.org/ ).
|
||||
|
||||
# The final tarball can be unpacked in the root directory of a RPi,
|
||||
# so the PhysicsFS install lands in /usr/local. Run ldconfig, and then
|
||||
# you should be able to build and run PhysicsFS-based software on your
|
||||
# Pi. Standard configure scripts should be able to find PhysicsFS and
|
||||
# build against it.
|
||||
|
||||
TARBALL="$1"
|
||||
if [ -z $1 ]; then
|
||||
TARBALL=physfs-raspberrypi.tar.xz
|
||||
fi
|
||||
|
||||
BUILDBOTDIR="buildbot"
|
||||
PARENTDIR="$PWD"
|
||||
|
||||
set -e
|
||||
set -x
|
||||
rm -f $TARBALL
|
||||
rm -rf $BUILDBOTDIR
|
||||
mkdir -p $BUILDBOTDIR
|
||||
pushd $BUILDBOTDIR
|
||||
|
||||
# the '-G "Ninja"' can be '-G "Unix Makefiles"' if you prefer to use GNU Make.
|
||||
SYSROOT="/opt/rpi-sysroot"
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_C_COMPILER="/opt/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc" \
|
||||
-DCMAKE_BUILD_TYPE=MinSizeRel \
|
||||
-DCMAKE_SYSROOT="$SYSROOT" \
|
||||
-DCMAKE_FIND_ROOT_PATH="$SYSROOT" \
|
||||
-DCMAKE_SYSTEM_NAME="Linux" \
|
||||
-DCMAKE_SYSTEM_VERSION=1 \
|
||||
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
|
||||
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
|
||||
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
|
||||
..
|
||||
|
||||
cmake --build . --config MinSizeRel
|
||||
|
||||
rm -rf "$TARBALL" physfs-raspberrypi
|
||||
mkdir -p physfs-raspberrypi
|
||||
echo "Archiving to '$TARBALL' ..."
|
||||
cp -a ../src/physfs.h libphysfs.a libphysfs.so* physfs-raspberrypi
|
||||
chmod -R a+r physfs-raspberrypi
|
||||
chmod a+x physfs-raspberrypi physfs-raspberrypi/*.so*
|
||||
chmod -R go-w physfs-raspberrypi
|
||||
tar -cJvvf "$TARBALL" physfs-raspberrypi
|
||||
|
||||
set +x
|
||||
echo "Done."
|
||||
|
||||
|
1414
third-party/physfs/extras/casefolding.txt
vendored
Normal file
1414
third-party/physfs/extras/casefolding.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
239
third-party/physfs/extras/globbing.c
vendored
Normal file
239
third-party/physfs/extras/globbing.c
vendored
Normal file
@ -0,0 +1,239 @@
|
||||
/** \file globbing.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "globbing.h"
|
||||
|
||||
/**
|
||||
* Please see globbing.h for details.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
|
||||
static int matchesPattern(const char *fname, const char *wildcard,
|
||||
int caseSensitive)
|
||||
{
|
||||
char x, y;
|
||||
const char *fnameptr = fname;
|
||||
const char *wildptr = wildcard;
|
||||
|
||||
while ((*wildptr) && (*fnameptr))
|
||||
{
|
||||
y = *wildptr;
|
||||
if (y == '*')
|
||||
{
|
||||
do
|
||||
{
|
||||
wildptr++; /* skip multiple '*' in a row... */
|
||||
} while (*wildptr == '*');
|
||||
|
||||
y = (caseSensitive) ? *wildptr : (char) tolower(*wildptr);
|
||||
|
||||
while (1)
|
||||
{
|
||||
x = (caseSensitive) ? *fnameptr : (char) tolower(*fnameptr);
|
||||
if ((!x) || (x == y))
|
||||
break;
|
||||
else
|
||||
fnameptr++;
|
||||
} /* while */
|
||||
} /* if */
|
||||
|
||||
else if (y == '?')
|
||||
{
|
||||
wildptr++;
|
||||
fnameptr++;
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
if (caseSensitive)
|
||||
x = *fnameptr;
|
||||
else
|
||||
{
|
||||
x = tolower(*fnameptr);
|
||||
y = tolower(y);
|
||||
} /* if */
|
||||
|
||||
wildptr++;
|
||||
fnameptr++;
|
||||
|
||||
if (x != y)
|
||||
return 0;
|
||||
} /* else */
|
||||
} /* while */
|
||||
|
||||
while (*wildptr == '*')
|
||||
wildptr++;
|
||||
|
||||
return (*fnameptr == *wildptr);
|
||||
} /* matchesPattern */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const PHYSFS_Allocator *allocator;
|
||||
const char *wildcard;
|
||||
int caseSensitive;
|
||||
PHYSFS_EnumFilesCallback callback;
|
||||
void *origData;
|
||||
} WildcardCallbackData;
|
||||
|
||||
|
||||
/*
|
||||
* This callback sits between the enumerator and the enduser callback,
|
||||
* filtering out files that don't match the wildcard pattern.
|
||||
*/
|
||||
static void wildcardCallback(void *_d, const char *origdir, const char *fname)
|
||||
{
|
||||
const WildcardCallbackData *data = (const WildcardCallbackData *) _d;
|
||||
if (matchesPattern(fname, data->wildcard, data->caseSensitive))
|
||||
data->callback(data->origData, origdir, fname);
|
||||
} /* wildcardCallback */
|
||||
|
||||
|
||||
void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive,
|
||||
PHYSFS_EnumFilesCallback c,
|
||||
void *d)
|
||||
{
|
||||
WildcardCallbackData data;
|
||||
data.allocator = PHYSFS_getAllocator();
|
||||
data.wildcard = wildcard;
|
||||
data.caseSensitive = caseSensitive;
|
||||
data.callback = c;
|
||||
data.origData = d;
|
||||
PHYSFS_enumerateFilesCallback(dir, wildcardCallback, &data);
|
||||
} /* PHYSFSEXT_enumerateFilesCallbackWildcard */
|
||||
|
||||
|
||||
void PHYSFSEXT_freeEnumeration(char **list)
|
||||
{
|
||||
const PHYSFS_Allocator *allocator = PHYSFS_getAllocator();
|
||||
int i;
|
||||
if (list != NULL)
|
||||
{
|
||||
for (i = 0; list[i] != NULL; i++)
|
||||
allocator->Free(list[i]);
|
||||
allocator->Free(list);
|
||||
} /* if */
|
||||
} /* PHYSFSEXT_freeEnumeration */
|
||||
|
||||
|
||||
char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard,
|
||||
int caseSensitive)
|
||||
{
|
||||
const PHYSFS_Allocator *allocator = PHYSFS_getAllocator();
|
||||
char **list = PHYSFS_enumerateFiles(dir);
|
||||
char **retval = NULL;
|
||||
int totalmatches = 0;
|
||||
int matches = 0;
|
||||
char **i;
|
||||
|
||||
for (i = list; *i != NULL; i++)
|
||||
{
|
||||
#if 0
|
||||
printf("matchesPattern: '%s' vs '%s' (%s) ... %s\n", *i, wildcard,
|
||||
caseSensitive ? "case" : "nocase",
|
||||
matchesPattern(*i, wildcard, caseSensitive) ? "true" : "false");
|
||||
#endif
|
||||
if (matchesPattern(*i, wildcard, caseSensitive))
|
||||
totalmatches++;
|
||||
} /* for */
|
||||
|
||||
retval = (char **) allocator->Malloc(sizeof (char *) * (totalmatches+1));
|
||||
if (retval != NULL)
|
||||
{
|
||||
for (i = list; ((matches < totalmatches) && (*i != NULL)); i++)
|
||||
{
|
||||
if (matchesPattern(*i, wildcard, caseSensitive))
|
||||
{
|
||||
retval[matches] = (char *) allocator->Malloc(strlen(*i) + 1);
|
||||
if (retval[matches] == NULL)
|
||||
{
|
||||
while (matches--)
|
||||
allocator->Free(retval[matches]);
|
||||
allocator->Free(retval);
|
||||
retval = NULL;
|
||||
break;
|
||||
} /* if */
|
||||
strcpy(retval[matches], *i);
|
||||
matches++;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
if (retval != NULL)
|
||||
{
|
||||
assert(totalmatches == matches);
|
||||
retval[matches] = NULL;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
PHYSFS_freeList(list);
|
||||
return retval;
|
||||
} /* PHYSFSEXT_enumerateFilesWildcard */
|
||||
|
||||
|
||||
#ifdef TEST_PHYSFSEXT_ENUMERATEFILESWILDCARD
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc;
|
||||
char **flist;
|
||||
char **i;
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("USAGE: %s <pattern> <caseSen>\n"
|
||||
" where <caseSen> is 1 or 0.\n", argv[0]);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_addToSearchPath(".", 1))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
flist = PHYSFSEXT_enumerateFilesWildcard("/", argv[1], atoi(argv[2]));
|
||||
rc = 0;
|
||||
for (i = flist; *i; i++)
|
||||
{
|
||||
printf("%s\n", *i);
|
||||
rc++;
|
||||
} /* for */
|
||||
printf("\n total %d files.\n\n", rc);
|
||||
|
||||
PHYSFSEXT_freeEnumeration(flist);
|
||||
PHYSFS_deinit();
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
#endif
|
||||
|
||||
/* end of globbing.c ... */
|
||||
|
165
third-party/physfs/extras/globbing.h
vendored
Normal file
165
third-party/physfs/extras/globbing.h
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
#ifndef INCL_PHYSFSEXT_GLOBBING_H
|
||||
#define INCL_PHYSFSEXT_GLOBBING_H
|
||||
|
||||
/** \file globbing.h */
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
/**
|
||||
* \mainpage PhysicsFS globbing
|
||||
*
|
||||
* This is an extension to PhysicsFS to let you search for files with basic
|
||||
* wildcard matching, regardless of what sort of filesystem or archive they
|
||||
* reside in. It does this by enumerating directories as needed and manually
|
||||
* locating matching entries.
|
||||
*
|
||||
* Usage: Set up PhysicsFS as you normally would, then use
|
||||
* PHYSFSEXT_enumerateFilesWildcard() when enumerating files. This is just
|
||||
* like PHYSFS_enumerateFiles(), but it returns a subset that matches your
|
||||
* wildcard pattern. You must call PHYSFSEXT_freeEnumeration() on the results,
|
||||
* just PHYSFS_enumerateFiles() would do with PHYSFS_freeList().
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the source's "docs" directory.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \fn char **PHYSFS_enumerateFilesWildcard(const char *dir, const char *wildcard, int caseSensitive)
|
||||
* \brief Get a file listing of a search path's directory, filtered with a wildcard pattern.
|
||||
*
|
||||
* Matching directories are interpolated. That is, if "C:\mydir" is in the
|
||||
* search path and contains a directory "savegames" that contains "x.sav",
|
||||
* "y.Sav", and "z.txt", and there is also a "C:\userdir" in the search path
|
||||
* that has a "savegames" subdirectory with "w.sav", then the following code:
|
||||
*
|
||||
* \code
|
||||
* char **rc = PHYSFS_enumerateFilesWildcard("savegames", "*.sav", 0);
|
||||
* char **i;
|
||||
*
|
||||
* for (i = rc; *i != NULL; i++)
|
||||
* printf(" * We've got [%s].\n", *i);
|
||||
*
|
||||
* PHYSFS_freeList(rc);
|
||||
* \endcode
|
||||
*
|
||||
* ...will print:
|
||||
*
|
||||
* \verbatim
|
||||
* We've got [x.sav].
|
||||
* We've got [y.Sav].
|
||||
* We've got [w.sav].\endverbatim
|
||||
*
|
||||
* Feel free to sort the list however you like. We only promise there will
|
||||
* be no duplicates, but not what order the final list will come back in.
|
||||
*
|
||||
* Wildcard strings can use the '*' and '?' characters, currently.
|
||||
* Matches can be case-insensitive if you pass a zero for argument 3.
|
||||
*
|
||||
* Don't forget to call PHYSFSEXT_freeEnumerator() with the return value from
|
||||
* this function when you are done with it. As we use PhysicsFS's allocator
|
||||
* for this list, you must free it before calling PHYSFS_deinit().
|
||||
* Do not use PHYSFS_freeList() on the returned value!
|
||||
*
|
||||
* \param dir directory in platform-independent notation to enumerate.
|
||||
* \param wildcard Wildcard pattern to use for filtering.
|
||||
* \param caseSensitive Zero for case-insensitive matching,
|
||||
* non-zero for case-sensitive.
|
||||
* \return Null-terminated array of null-terminated strings.
|
||||
*
|
||||
* \sa PHYSFSEXT_freeEnumeration
|
||||
*/
|
||||
PHYSFS_DECL char **PHYSFSEXT_enumerateFilesWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive);
|
||||
|
||||
/**
|
||||
* \fn void PHYSFSEXT_freeEnumeration(char **list)
|
||||
* \brief Free data returned by PHYSFSEXT_enumerateFilesWildcard
|
||||
*
|
||||
* Conceptually, this works like PHYSFS_freeList(), but is used with data
|
||||
* returned by PHYSFSEXT_enumerateFilesWildcard() only. Be sure to call this
|
||||
* on any returned data from that function before
|
||||
*
|
||||
* \param list Pointer previously returned by
|
||||
* PHYSFSEXT_enumerateFilesWildcard(). It is safe to pass a
|
||||
* NULL here.
|
||||
*
|
||||
* \sa PHYSFSEXT_enumerateFilesWildcard
|
||||
*/
|
||||
PHYSFS_DECL void PHYSFSEXT_freeEnumeration(char **list);
|
||||
|
||||
|
||||
/**
|
||||
* \fn void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir, const char *wildcard, int caseSensitive, PHYSFS_EnumFilesCallback c, void *d);
|
||||
* \brief Get a file listing of a search path's directory, filtered with a wildcard pattern, using an application-defined callback.
|
||||
*
|
||||
* This function is equivalent to PHYSFSEXT_enumerateFilesWildcard(). It
|
||||
* reports file listings, filtered by a wildcard pattern.
|
||||
*
|
||||
* Unlike PHYSFS_enumerateFiles(), this function does not return an array.
|
||||
* Rather, it calls a function specified by the application once per
|
||||
* element of the search path:
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* static void printDir(void *data, const char *origdir, const char *fname)
|
||||
* {
|
||||
* printf(" * We've got [%s] in [%s].\n", fname, origdir);
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* PHYSFS_enumerateFilesCallbackWildcard("savegames","*.sav",0,printDir,NULL);
|
||||
* \endcode
|
||||
*
|
||||
* Items sent to the callback are not guaranteed to be in any order whatsoever.
|
||||
* There is no sorting done at this level, and if you need that, you should
|
||||
* probably use PHYSFS_enumerateFilesWildcard() instead, which guarantees
|
||||
* alphabetical sorting. This form reports whatever is discovered in each
|
||||
* archive before moving on to the next. Even within one archive, we can't
|
||||
* guarantee what order it will discover data. <em>Any sorting you find in
|
||||
* these callbacks is just pure luck. Do not rely on it.</em> As this walks
|
||||
* the entire list of archives, you may receive duplicate filenames.
|
||||
*
|
||||
* Wildcard strings can use the '*' and '?' characters, currently.
|
||||
* Matches can be case-insensitive if you pass a zero for argument 3.
|
||||
*
|
||||
* \param dir Directory, in platform-independent notation, to enumerate.
|
||||
* \param wildcard Wildcard pattern to use for filtering.
|
||||
* \param caseSensitive Zero for case-insensitive matching,
|
||||
* non-zero for case-sensitive.
|
||||
* \param c Callback function to notify about search path elements.
|
||||
* \param d Application-defined data passed to callback. Can be NULL.
|
||||
*
|
||||
* \sa PHYSFS_EnumFilesCallback
|
||||
* \sa PHYSFS_enumerateFiles
|
||||
*/
|
||||
PHYSFS_DECL void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive,
|
||||
PHYSFS_EnumFilesCallback c,
|
||||
void *d);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker. */
|
||||
|
||||
/* end of globbing.h ... */
|
||||
|
203
third-party/physfs/extras/ignorecase.c
vendored
Normal file
203
third-party/physfs/extras/ignorecase.c
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
/** \file ignorecase.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "physfs.h"
|
||||
#include "ignorecase.h"
|
||||
|
||||
/**
|
||||
* Please see ignorecase.h for details.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
static int locateOneElement(char *buf)
|
||||
{
|
||||
char *ptr;
|
||||
char **rc;
|
||||
char **i;
|
||||
|
||||
if (PHYSFS_exists(buf))
|
||||
return 1; /* quick rejection: exists in current case. */
|
||||
|
||||
ptr = strrchr(buf, '/'); /* find entry at end of path. */
|
||||
if (ptr == NULL)
|
||||
{
|
||||
rc = PHYSFS_enumerateFiles("/");
|
||||
ptr = buf;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
*ptr = '\0';
|
||||
rc = PHYSFS_enumerateFiles(buf);
|
||||
*ptr = '/';
|
||||
ptr++; /* point past dirsep to entry itself. */
|
||||
} /* else */
|
||||
|
||||
if (rc != NULL)
|
||||
{
|
||||
for (i = rc; *i != NULL; i++)
|
||||
{
|
||||
if (PHYSFS_utf8stricmp(*i, ptr) == 0)
|
||||
{
|
||||
strcpy(ptr, *i); /* found a match. Overwrite with this case. */
|
||||
PHYSFS_freeList(rc);
|
||||
return 1;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
PHYSFS_freeList(rc);
|
||||
} /* if */
|
||||
|
||||
/* no match at all... */
|
||||
return 0;
|
||||
} /* locateOneElement */
|
||||
|
||||
|
||||
int PHYSFSEXT_locateCorrectCase(char *buf)
|
||||
{
|
||||
int rc;
|
||||
char *ptr;
|
||||
|
||||
while (*buf == '/') /* skip any '/' at start of string... */
|
||||
buf++;
|
||||
|
||||
ptr = buf;
|
||||
if (*ptr == '\0')
|
||||
return 0; /* Uh...I guess that's success. */
|
||||
|
||||
while ( (ptr = strchr(ptr + 1, '/')) != NULL )
|
||||
{
|
||||
*ptr = '\0'; /* block this path section off */
|
||||
rc = locateOneElement(buf);
|
||||
*ptr = '/'; /* restore path separator */
|
||||
if (!rc)
|
||||
return -2; /* missing element in path. */
|
||||
} /* while */
|
||||
|
||||
/* check final element... */
|
||||
return locateOneElement(buf) ? 0 : -1;
|
||||
} /* PHYSFSEXT_locateCorrectCase */
|
||||
|
||||
|
||||
#ifdef TEST_PHYSFSEXT_LOCATECORRECTCASE
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc;
|
||||
char buf[128];
|
||||
PHYSFS_File *f;
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_addToSearchPath(".", 1))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_setWriteDir("."))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_setWriteDir(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_mkdir("/a/b/c"))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_mkdir(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_mkdir("/a/b/C"))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_mkdir(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
f = PHYSFS_openWrite("/a/b/c/x.txt");
|
||||
PHYSFS_close(f);
|
||||
if (f == NULL)
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_openWrite(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
f = PHYSFS_openWrite("/a/b/C/X.txt");
|
||||
PHYSFS_close(f);
|
||||
if (f == NULL)
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_openWrite(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
strcpy(buf, "/a/b/c/x.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != 0) || (strcmp(buf, "/a/b/c/x.txt") != 0))
|
||||
printf("test 1 failed\n");
|
||||
|
||||
strcpy(buf, "/a/B/c/x.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != 0) || (strcmp(buf, "/a/b/c/x.txt") != 0))
|
||||
printf("test 2 failed\n");
|
||||
|
||||
strcpy(buf, "/a/b/C/x.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != 0) || (strcmp(buf, "/a/b/C/X.txt") != 0))
|
||||
printf("test 3 failed\n");
|
||||
|
||||
strcpy(buf, "/a/b/c/X.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != 0) || (strcmp(buf, "/a/b/c/x.txt") != 0))
|
||||
printf("test 4 failed\n");
|
||||
|
||||
strcpy(buf, "/a/b/c/z.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != -1) || (strcmp(buf, "/a/b/c/z.txt") != 0))
|
||||
printf("test 5 failed\n");
|
||||
|
||||
strcpy(buf, "/A/B/Z/z.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != -2) || (strcmp(buf, "/a/b/Z/z.txt") != 0))
|
||||
printf("test 6 failed\n");
|
||||
|
||||
printf("Testing completed.\n");
|
||||
printf(" If no errors were reported, you're good to go.\n");
|
||||
|
||||
PHYSFS_delete("/a/b/c/x.txt");
|
||||
PHYSFS_delete("/a/b/C/X.txt");
|
||||
PHYSFS_delete("/a/b/c");
|
||||
PHYSFS_delete("/a/b/C");
|
||||
PHYSFS_delete("/a/b");
|
||||
PHYSFS_delete("/a");
|
||||
PHYSFS_deinit();
|
||||
return 0;
|
||||
} /* main */
|
||||
#endif
|
||||
|
||||
/* end of ignorecase.c ... */
|
||||
|
86
third-party/physfs/extras/ignorecase.h
vendored
Normal file
86
third-party/physfs/extras/ignorecase.h
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
#ifndef INCL_PHYSFSEXT_IGNORECASE_H
|
||||
#define INCL_PHYSFSEXT_IGNORECASE_H
|
||||
|
||||
/** \file ignorecase.h */
|
||||
|
||||
/**
|
||||
* \mainpage PhysicsFS ignorecase
|
||||
*
|
||||
* This is an extension to PhysicsFS to let you handle files in a
|
||||
* case-insensitive manner, regardless of what sort of filesystem or
|
||||
* archive they reside in. It does this by enumerating directories as
|
||||
* needed and manually locating matching entries.
|
||||
*
|
||||
* Please note that this brings with it some caveats:
|
||||
* - On filesystems that are case-insensitive to start with, such as those
|
||||
* used on Windows or MacOS, you are adding extra overhead.
|
||||
* - On filesystems that are case-sensitive, you might select the wrong dir
|
||||
* or file (which brings security considerations and potential bugs). This
|
||||
* code favours exact case matches, but you will lose access to otherwise
|
||||
* duplicate filenames, or you might go down a wrong directory tree, etc.
|
||||
* In practice, this is rarely a problem, but you need to be aware of it.
|
||||
* - This doesn't do _anything_ with the write directory; you're on your
|
||||
* own for opening the right files for writing. You can sort of get around
|
||||
* this by adding your write directory to the search path, but then the
|
||||
* interpolated directory tree can screw you up even more.
|
||||
*
|
||||
* This code should be considered an aid for legacy code. New development
|
||||
* shouldn't do things that require this aid in the first place. :)
|
||||
*
|
||||
* Usage: Set up PhysicsFS as you normally would, then use
|
||||
* PHYSFSEXT_locateCorrectCase() to get a "correct" pathname to pass to
|
||||
* functions like PHYSFS_openRead(), etc.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \fn int PHYSFSEXT_locateCorrectCase(char *buf)
|
||||
* \brief Find an existing filename with matching case.
|
||||
*
|
||||
* This function will look for a path/filename that matches the passed in
|
||||
* buffer. Each element of the buffer's path is checked for a
|
||||
* case-insensitive match. The buffer must specify a null-terminated string
|
||||
* in platform-independent notation.
|
||||
*
|
||||
* Please note results may be skewed differently depending on whether symlinks
|
||||
* are enabled or not.
|
||||
*
|
||||
* Each element of the buffer is overwritten with the actual case of an
|
||||
* existing match. If there is no match, the search aborts and reports an
|
||||
* error. Exact matches are favored over case-insensitive matches.
|
||||
*
|
||||
* THIS IS RISKY. Please do not use this function for anything but legacy code.
|
||||
*
|
||||
* \param buf Buffer with null-terminated string of path/file to locate.
|
||||
* This buffer will be modified by this function.
|
||||
* \return zero if match was found, -1 if the final element (the file itself)
|
||||
* is missing, -2 if one of the parent directories is missing.
|
||||
*/
|
||||
int PHYSFSEXT_locateCorrectCase(char *buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker. */
|
||||
|
||||
/* end of ignorecase.h ... */
|
||||
|
276
third-party/physfs/extras/makecasefoldhashtable.pl
vendored
Normal file
276
third-party/physfs/extras/makecasefoldhashtable.pl
vendored
Normal file
@ -0,0 +1,276 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
my $HASHBUCKETS1_16 = 256;
|
||||
my $HASHBUCKETS1_32 = 16;
|
||||
my $HASHBUCKETS2_16 = 16;
|
||||
my $HASHBUCKETS3_16 = 4;
|
||||
|
||||
print <<__EOF__;
|
||||
/*
|
||||
* This file is part of PhysicsFS (https://icculus.org/physfs/)
|
||||
*
|
||||
* This data generated by physfs/extras/makecasefoldhashtable.pl ...
|
||||
* Do not manually edit this file!
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_PHYSFS_CASEFOLDING_H_
|
||||
#define _INCLUDE_PHYSFS_CASEFOLDING_H_
|
||||
|
||||
#ifndef __PHYSICSFS_INTERNAL__
|
||||
#error Do not include this header from your applications.
|
||||
#endif
|
||||
|
||||
/* We build three simple hashmaps here: one that maps Unicode codepoints to
|
||||
a one, two, or three lowercase codepoints. To retrieve this info: look at
|
||||
case_fold_hashX, where X is 1, 2, or 3. Most foldable codepoints fold to one,
|
||||
a few dozen fold to two, and a handful fold to three. If the codepoint isn't
|
||||
in any of these hashes, it doesn't fold (no separate upper and lowercase).
|
||||
|
||||
Almost all these codepoints fit into 16 bits, so we hash them as such to save
|
||||
memory. If a codepoint is > 0xFFFF, we have separate hashes for them,
|
||||
since there are (currently) only about 120 of them and (currently) all of them
|
||||
map to a single lowercase codepoint. */
|
||||
|
||||
typedef struct CaseFoldMapping1_32
|
||||
{
|
||||
PHYSFS_uint32 from;
|
||||
PHYSFS_uint32 to0;
|
||||
} CaseFoldMapping1_32;
|
||||
|
||||
typedef struct CaseFoldMapping1_16
|
||||
{
|
||||
PHYSFS_uint16 from;
|
||||
PHYSFS_uint16 to0;
|
||||
} CaseFoldMapping1_16;
|
||||
|
||||
typedef struct CaseFoldMapping2_16
|
||||
{
|
||||
PHYSFS_uint16 from;
|
||||
PHYSFS_uint16 to0;
|
||||
PHYSFS_uint16 to1;
|
||||
} CaseFoldMapping2_16;
|
||||
|
||||
typedef struct CaseFoldMapping3_16
|
||||
{
|
||||
PHYSFS_uint16 from;
|
||||
PHYSFS_uint16 to0;
|
||||
PHYSFS_uint16 to1;
|
||||
PHYSFS_uint16 to2;
|
||||
} CaseFoldMapping3_16;
|
||||
|
||||
typedef struct CaseFoldHashBucket1_16
|
||||
{
|
||||
const CaseFoldMapping1_16 *list;
|
||||
const PHYSFS_uint8 count;
|
||||
} CaseFoldHashBucket1_16;
|
||||
|
||||
typedef struct CaseFoldHashBucket1_32
|
||||
{
|
||||
const CaseFoldMapping1_32 *list;
|
||||
const PHYSFS_uint8 count;
|
||||
} CaseFoldHashBucket1_32;
|
||||
|
||||
typedef struct CaseFoldHashBucket2_16
|
||||
{
|
||||
const CaseFoldMapping2_16 *list;
|
||||
const PHYSFS_uint8 count;
|
||||
} CaseFoldHashBucket2_16;
|
||||
|
||||
typedef struct CaseFoldHashBucket3_16
|
||||
{
|
||||
const CaseFoldMapping3_16 *list;
|
||||
const PHYSFS_uint8 count;
|
||||
} CaseFoldHashBucket3_16;
|
||||
|
||||
__EOF__
|
||||
|
||||
|
||||
my @foldPairs1_16;
|
||||
my @foldPairs2_16;
|
||||
my @foldPairs3_16;
|
||||
my @foldPairs1_32;
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) {
|
||||
$foldPairs1_16[$i] = '';
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) {
|
||||
$foldPairs1_32[$i] = '';
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) {
|
||||
$foldPairs2_16[$i] = '';
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) {
|
||||
$foldPairs3_16[$i] = '';
|
||||
}
|
||||
|
||||
open(FH,'<','casefolding.txt') or die("failed to open casefolding.txt: $!\n");
|
||||
while (<FH>) {
|
||||
chomp;
|
||||
# strip comments from textfile...
|
||||
s/\#.*\Z//;
|
||||
|
||||
# strip whitespace...
|
||||
s/\A\s+//;
|
||||
s/\s+\Z//;
|
||||
|
||||
next if not /\A([a-fA-F0-9]+)\;\s*(.)\;\s*(.+)\;/;
|
||||
my ($code, $status, $mapping) = ($1, $2, $3);
|
||||
|
||||
my $hexxed = hex($code);
|
||||
#print("// code '$code' status '$status' mapping '$mapping'\n");
|
||||
|
||||
if (($status eq 'C') or ($status eq 'F')) {
|
||||
my ($map1, $map2, $map3) = (undef, undef, undef);
|
||||
$map1 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
||||
$map2 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
||||
$map3 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
||||
die("mapping space too small for '$code'\n") if ($mapping ne '');
|
||||
die("problem parsing mapping for '$code'\n") if (not defined($map1));
|
||||
|
||||
if ($hexxed < 128) {
|
||||
# Just ignore these, we'll handle the low-ASCII ones ourselves.
|
||||
} elsif ($hexxed > 0xFFFF) {
|
||||
# We just need to add the 32-bit 2 and/or 3 codepoint maps if this die()'s here.
|
||||
die("Uhoh, a codepoint > 0xFFFF that folds to multiple codepoints! Fixme.") if defined($map2);
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS1_32-1));
|
||||
#print("// hexxed '$hexxed' hashed1 '$hashed'\n");
|
||||
$foldPairs1_32[$hashed] .= " { 0x$code, 0x$map1 },\n";
|
||||
} elsif (not defined($map2)) {
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS1_16-1));
|
||||
#print("// hexxed '$hexxed' hashed1 '$hashed'\n");
|
||||
$foldPairs1_16[$hashed] .= " { 0x$code, 0x$map1 },\n";
|
||||
} elsif (not defined($map3)) {
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS2_16-1));
|
||||
#print("// hexxed '$hexxed' hashed2 '$hashed'\n");
|
||||
$foldPairs2_16[$hashed] .= " { 0x$code, 0x$map1, 0x$map2 },\n";
|
||||
} else {
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS3_16-1));
|
||||
#print("// hexxed '$hexxed' hashed3 '$hashed'\n");
|
||||
$foldPairs3_16[$hashed] .= " { 0x$code, 0x$map1, 0x$map2, 0x$map3 },\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
close(FH);
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) {
|
||||
$foldPairs1_16[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs1_16[$i];
|
||||
next if $str eq '';
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold1_16_${num}";
|
||||
print("static const CaseFoldMapping1_16 ${sym}[] = {\n$str\n};\n\n");
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) {
|
||||
$foldPairs1_32[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs1_32[$i];
|
||||
next if $str eq '';
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold1_32_${num}";
|
||||
print("static const CaseFoldMapping1_32 ${sym}[] = {\n$str\n};\n\n");
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) {
|
||||
$foldPairs2_16[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs2_16[$i];
|
||||
next if $str eq '';
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold2_16_${num}";
|
||||
print("static const CaseFoldMapping2_16 ${sym}[] = {\n$str\n};\n\n");
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) {
|
||||
$foldPairs3_16[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs3_16[$i];
|
||||
next if $str eq '';
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold3_16_${num}";
|
||||
print("static const CaseFoldMapping3_16 ${sym}[] = {\n$str\n};\n\n");
|
||||
}
|
||||
|
||||
print("static const CaseFoldHashBucket1_16 case_fold_hash1_16[] = {\n");
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) {
|
||||
my $str = $foldPairs1_16[$i];
|
||||
if ($str eq '') {
|
||||
print(" { NULL, 0 },\n");
|
||||
} else {
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold1_16_${num}";
|
||||
print(" { $sym, __PHYSFS_ARRAYLEN($sym) },\n");
|
||||
}
|
||||
}
|
||||
print("};\n\n");
|
||||
|
||||
|
||||
print("static const CaseFoldHashBucket1_32 case_fold_hash1_32[] = {\n");
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) {
|
||||
my $str = $foldPairs1_32[$i];
|
||||
if ($str eq '') {
|
||||
print(" { NULL, 0 },\n");
|
||||
} else {
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold1_32_${num}";
|
||||
print(" { $sym, __PHYSFS_ARRAYLEN($sym) },\n");
|
||||
}
|
||||
}
|
||||
print("};\n\n");
|
||||
|
||||
|
||||
print("static const CaseFoldHashBucket2_16 case_fold_hash2_16[] = {\n");
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) {
|
||||
my $str = $foldPairs2_16[$i];
|
||||
if ($str eq '') {
|
||||
print(" { NULL, 0 },\n");
|
||||
} else {
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold2_16_${num}";
|
||||
print(" { $sym, __PHYSFS_ARRAYLEN($sym) },\n");
|
||||
}
|
||||
}
|
||||
print("};\n\n");
|
||||
|
||||
print("static const CaseFoldHashBucket3_16 case_fold_hash3_16[] = {\n");
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) {
|
||||
my $str = $foldPairs3_16[$i];
|
||||
if ($str eq '') {
|
||||
print(" { NULL, 0 },\n");
|
||||
} else {
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold3_16_${num}";
|
||||
print(" { $sym, __PHYSFS_ARRAYLEN($sym) },\n");
|
||||
}
|
||||
}
|
||||
print("};\n\n");
|
||||
|
||||
print <<__EOF__;
|
||||
|
||||
#endif /* _INCLUDE_PHYSFS_CASEFOLDING_H_ */
|
||||
|
||||
/* end of physfs_casefolding.h ... */
|
||||
|
||||
__EOF__
|
||||
|
||||
exit 0;
|
||||
|
||||
# end of makecashfoldhashtable.pl ...
|
||||
|
11
third-party/physfs/extras/physfs.pc.in
vendored
Normal file
11
third-party/physfs/extras/physfs.pc.in
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
|
||||
Name: PhysicsFS
|
||||
Description: PhysicsFS is a library to provide abstract access to various archives.
|
||||
URL: https://icculus.org/physfs/
|
||||
Version: @PHYSFS_VERSION@
|
||||
Libs: -L${libdir} -lphysfs
|
||||
Cflags: -I${includedir}
|
400
third-party/physfs/extras/physfshttpd.c
vendored
Normal file
400
third-party/physfs/extras/physfshttpd.c
vendored
Normal file
@ -0,0 +1,400 @@
|
||||
/*
|
||||
* This is a quick and dirty HTTP server that uses PhysicsFS to retrieve
|
||||
* files. It is not robust at all, probably buggy, and definitely poorly
|
||||
* designed. It's just meant to show that it can be done.
|
||||
*
|
||||
* Basically, you compile this code, and run it:
|
||||
* ./physfshttpd archive1.zip archive2.zip /path/to/a/real/dir etc...
|
||||
*
|
||||
* The files are appended in order to the PhysicsFS search path, and when
|
||||
* a client request comes in, it looks for the file in said search path.
|
||||
*
|
||||
* My goal was to make this work in less than 300 lines of C, so again, it's
|
||||
* not to be used for any serious purpose. Patches to make this application
|
||||
* suck less will be readily and gratefully accepted.
|
||||
*
|
||||
* Command line I used to build this on Linux:
|
||||
* gcc -Wall -Werror -g -o bin/physfshttpd extras/physfshttpd.c -lphysfs
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifndef LACKING_SIGNALS
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifndef LACKING_PROTOENT
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
|
||||
#define DEFAULT_PORTNUM 8080
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr *addr;
|
||||
socklen_t addrlen;
|
||||
} http_args;
|
||||
|
||||
|
||||
#define txt404 \
|
||||
"HTTP/1.0 404 Not Found\n" \
|
||||
"Connection: close\n" \
|
||||
"Content-Type: text/html; charset=utf-8\n" \
|
||||
"\n" \
|
||||
"<html><head><title>404 Not Found</title></head>\n" \
|
||||
"<body>Can't find '%s'.</body></html>\n\n" \
|
||||
|
||||
#define txt200 \
|
||||
"HTTP/1.0 200 OK\n" \
|
||||
"Connection: close\n" \
|
||||
"Content-Type: %s\n" \
|
||||
"\n"
|
||||
|
||||
static const char *lastError(void)
|
||||
{
|
||||
return PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
|
||||
} /* lastError */
|
||||
|
||||
static int writeAll(const char *ipstr, const int sock, void *buf, const size_t len)
|
||||
{
|
||||
if (write(sock, buf, len) != len)
|
||||
{
|
||||
printf("%s: Write error to socket.\n", ipstr);
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
return 1;
|
||||
} /* writeAll */
|
||||
|
||||
static int writeString(const char *ipstr, const int sock, const char *fmt, ...)
|
||||
{
|
||||
/* none of this is robust against large strings or HTML escaping. */
|
||||
char buffer[1024];
|
||||
int len;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buffer, sizeof (buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
if (len < 0)
|
||||
{
|
||||
printf("uhoh, vsnprintf() failed!\n");
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
return writeAll(ipstr, sock, buffer, len);
|
||||
} /* writeString */
|
||||
|
||||
|
||||
static void feed_file_http(const char *ipstr, int sock, const char *fname)
|
||||
{
|
||||
PHYSFS_File *in = PHYSFS_openRead(fname);
|
||||
|
||||
if (in == NULL)
|
||||
{
|
||||
printf("%s: Can't open [%s]: %s.\n", ipstr, fname, lastError());
|
||||
writeString(ipstr, sock, txt404, fname);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
/* !!! FIXME: mimetype */
|
||||
if (writeString(ipstr, sock, txt200, "text/plain; charset=utf-8"))
|
||||
{
|
||||
do
|
||||
{
|
||||
char buffer[1024];
|
||||
PHYSFS_sint64 br = PHYSFS_readBytes(in, buffer, sizeof (buffer));
|
||||
if (br == -1)
|
||||
{
|
||||
printf("%s: Read error: %s.\n", ipstr, lastError());
|
||||
break;
|
||||
} /* if */
|
||||
|
||||
else if (!writeAll(ipstr, sock, buffer, (size_t) br))
|
||||
{
|
||||
break;
|
||||
} /* else if */
|
||||
} while (!PHYSFS_eof(in));
|
||||
} /* if */
|
||||
|
||||
PHYSFS_close(in);
|
||||
} /* feed_file_http */
|
||||
|
||||
|
||||
static void feed_dirlist_http(const char *ipstr, int sock,
|
||||
const char *dname, char **list)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!writeString(ipstr, sock, txt200, "text/html; charset=utf-8"))
|
||||
return;
|
||||
|
||||
else if (!writeString(ipstr, sock,
|
||||
"<html><head><title>Directory %s</title></head>"
|
||||
"<body><p><h1>Directory %s</h1></p><p><ul>\n",
|
||||
dname, dname))
|
||||
return;
|
||||
|
||||
if (strcmp(dname, "/") == 0)
|
||||
dname = "";
|
||||
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
const char *fname = list[i];
|
||||
if (!writeString(ipstr, sock,
|
||||
"<li><a href='%s/%s'>%s</a></li>\n", dname, fname, fname))
|
||||
break;
|
||||
} /* for */
|
||||
|
||||
writeString(ipstr, sock, "</ul></body></html>\n");
|
||||
} /* feed_dirlist_http */
|
||||
|
||||
static void feed_dir_http(const char *ipstr, int sock, const char *dname)
|
||||
{
|
||||
char **list = PHYSFS_enumerateFiles(dname);
|
||||
if (list == NULL)
|
||||
{
|
||||
printf("%s: Can't enumerate directory [%s]: %s.\n",
|
||||
ipstr, dname, lastError());
|
||||
writeString(ipstr, sock, txt404, dname);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
feed_dirlist_http(ipstr, sock, dname, list);
|
||||
PHYSFS_freeList(list);
|
||||
} /* feed_dir_http */
|
||||
|
||||
static void feed_http_request(const char *ipstr, int sock, const char *fname)
|
||||
{
|
||||
PHYSFS_Stat statbuf;
|
||||
|
||||
printf("%s: requested [%s].\n", ipstr, fname);
|
||||
|
||||
if (!PHYSFS_stat(fname, &statbuf))
|
||||
{
|
||||
printf("%s: Can't stat [%s]: %s.\n", ipstr, fname, lastError());
|
||||
writeString(ipstr, sock, txt404, fname);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
if (statbuf.filetype == PHYSFS_FILETYPE_DIRECTORY)
|
||||
feed_dir_http(ipstr, sock, fname);
|
||||
else
|
||||
feed_file_http(ipstr, sock, fname);
|
||||
} /* feed_http_request */
|
||||
|
||||
|
||||
static void *do_http(void *_args)
|
||||
{
|
||||
http_args *args = (http_args *) _args;
|
||||
char ipstr[128];
|
||||
char buffer[512];
|
||||
char *ptr;
|
||||
strncpy(ipstr, inet_ntoa(((struct sockaddr_in *) args->addr)->sin_addr),
|
||||
sizeof (ipstr));
|
||||
ipstr[sizeof (ipstr) - 1] = '\0';
|
||||
|
||||
printf("%s: connected.\n", ipstr);
|
||||
read(args->sock, buffer, sizeof (buffer));
|
||||
buffer[sizeof (buffer) - 1] = '\0';
|
||||
ptr = strchr(buffer, '\n');
|
||||
if (!ptr)
|
||||
printf("%s: potentially bogus request.\n", ipstr);
|
||||
else
|
||||
{
|
||||
*ptr = '\0';
|
||||
ptr = strchr(buffer, '\r');
|
||||
if (ptr != NULL)
|
||||
*ptr = '\0';
|
||||
|
||||
if ((toupper(buffer[0]) == 'G') &&
|
||||
(toupper(buffer[1]) == 'E') &&
|
||||
(toupper(buffer[2]) == 'T') &&
|
||||
(toupper(buffer[3]) == ' ') &&
|
||||
(toupper(buffer[4]) == '/'))
|
||||
{
|
||||
ptr = strchr(buffer + 5, ' ');
|
||||
if (ptr != NULL)
|
||||
*ptr = '\0';
|
||||
feed_http_request(ipstr, args->sock, buffer + 4);
|
||||
} /* if */
|
||||
} /* else */
|
||||
|
||||
/* !!! FIXME: Time the transfer. */
|
||||
printf("%s: closing connection.\n", ipstr);
|
||||
close(args->sock);
|
||||
free(args->addr);
|
||||
free(args);
|
||||
return NULL;
|
||||
} /* do_http */
|
||||
|
||||
|
||||
static void serve_http_request(int sock, struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
http_args *args = (http_args *) malloc(sizeof (http_args));
|
||||
if (args == NULL)
|
||||
{
|
||||
printf("out of memory.\n");
|
||||
return;
|
||||
} /* if */
|
||||
args->addr = (struct sockaddr *) malloc(addrlen);
|
||||
if (args->addr == NULL)
|
||||
{
|
||||
free(args);
|
||||
printf("out of memory.\n");
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
args->sock = sock;
|
||||
args->addrlen = addrlen;
|
||||
memcpy(args->addr, addr, addrlen);
|
||||
|
||||
/* !!! FIXME: optionally spin a thread... */
|
||||
do_http((void *) args);
|
||||
} /* server_http_request */
|
||||
|
||||
|
||||
static int create_listen_socket(short portnum)
|
||||
{
|
||||
int retval = -1;
|
||||
int protocol = 0; /* pray this is right. */
|
||||
|
||||
#ifndef LACKING_PROTOENT
|
||||
struct protoent *prot;
|
||||
setprotoent(0);
|
||||
prot = getprotobyname("tcp");
|
||||
if (prot != NULL)
|
||||
protocol = prot->p_proto;
|
||||
#endif
|
||||
|
||||
retval = socket(PF_INET, SOCK_STREAM, protocol);
|
||||
if (retval >= 0)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(portnum);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if ((bind(retval, (struct sockaddr *) &addr, (socklen_t) sizeof (addr)) == -1) ||
|
||||
(listen(retval, 5) == -1))
|
||||
{
|
||||
close(retval);
|
||||
retval = -1;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
return retval;
|
||||
} /* create_listen_socket */
|
||||
|
||||
|
||||
static int listensocket = -1;
|
||||
|
||||
void at_exit_cleanup(void)
|
||||
{
|
||||
/*
|
||||
* !!! FIXME: If thread support, signal threads to terminate and
|
||||
* !!! FIXME: wait for them to clean up.
|
||||
*/
|
||||
|
||||
if (listensocket >= 0)
|
||||
close(listensocket);
|
||||
|
||||
if (!PHYSFS_deinit())
|
||||
printf("PHYSFS_deinit() failed: %s\n", lastError());
|
||||
} /* at_exit_cleanup */
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
int portnum = DEFAULT_PORTNUM;
|
||||
|
||||
setbuf(stdout, NULL);
|
||||
setbuf(stderr, NULL);
|
||||
|
||||
#ifndef LACKING_SIGNALS
|
||||
/* I'm not sure if this qualifies as a cheap trick... */
|
||||
signal(SIGTERM, exit);
|
||||
signal(SIGINT, exit);
|
||||
signal(SIGFPE, exit);
|
||||
signal(SIGSEGV, exit);
|
||||
signal(SIGPIPE, exit);
|
||||
signal(SIGILL, exit);
|
||||
#endif
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
printf("USAGE: %s <archive1> [archive2 [... archiveN]]\n", argv[0]);
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
printf("PHYSFS_init() failed: %s\n", lastError());
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
/* normally, this is bad practice, but oh well. */
|
||||
atexit(at_exit_cleanup);
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (!PHYSFS_mount(argv[i], NULL, 1))
|
||||
printf(" WARNING: failed to add [%s] to search path.\n", argv[i]);
|
||||
} /* else */
|
||||
|
||||
listensocket = create_listen_socket(portnum);
|
||||
if (listensocket < 0)
|
||||
{
|
||||
printf("listen socket failed to create.\n");
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
while (1) /* infinite loop for now. */
|
||||
{
|
||||
struct sockaddr addr;
|
||||
socklen_t len;
|
||||
int s = accept(listensocket, &addr, &len);
|
||||
if (s < 0)
|
||||
{
|
||||
printf("accept() failed: %s\n", strerror(errno));
|
||||
close(listensocket);
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
serve_http_request(s, &addr, len);
|
||||
} /* while */
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
/* end of physfshttpd.c ... */
|
||||
|
251
third-party/physfs/extras/physfsrwops.c
vendored
Normal file
251
third-party/physfs/extras/physfsrwops.c
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* This code provides a glue layer between PhysicsFS and Simple Directmedia
|
||||
* Layer's (SDL) RWops i/o abstraction.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* SDL 1.2 falls under the LGPL license. SDL 1.3+ is zlib, like PhysicsFS.
|
||||
* You can get SDL at https://www.libsdl.org/
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
|
||||
#include "physfsrwops.h"
|
||||
|
||||
/* SDL's RWOPS interface changed a little in SDL 2.0... */
|
||||
#if defined(SDL_VERSION_ATLEAST)
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#define TARGET_SDL2 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !TARGET_SDL2
|
||||
#ifndef RW_SEEK_SET
|
||||
#define RW_SEEK_SET SEEK_SET
|
||||
#endif
|
||||
#ifndef RW_SEEK_CUR
|
||||
#define RW_SEEK_CUR SEEK_CUR
|
||||
#endif
|
||||
#ifndef RW_SEEK_END
|
||||
#define RW_SEEK_END SEEK_END
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TARGET_SDL2
|
||||
static Sint64 SDLCALL physfsrwops_size(struct SDL_RWops *rw)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
return (Sint64) PHYSFS_fileLength(handle);
|
||||
} /* physfsrwops_size */
|
||||
#endif
|
||||
|
||||
|
||||
#if TARGET_SDL2
|
||||
static Sint64 SDLCALL physfsrwops_seek(struct SDL_RWops *rw, Sint64 offset, int whence)
|
||||
#else
|
||||
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
|
||||
#endif
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 pos = 0;
|
||||
|
||||
if (whence == RW_SEEK_SET)
|
||||
pos = (PHYSFS_sint64) offset;
|
||||
|
||||
else if (whence == RW_SEEK_CUR)
|
||||
{
|
||||
const PHYSFS_sint64 current = PHYSFS_tell(handle);
|
||||
if (current == -1)
|
||||
{
|
||||
SDL_SetError("Can't find position in file: %s",
|
||||
PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
if (offset == 0) /* this is a "tell" call. We're done. */
|
||||
{
|
||||
#if TARGET_SDL2
|
||||
return (Sint64) current;
|
||||
#else
|
||||
return (int) current;
|
||||
#endif
|
||||
} /* if */
|
||||
|
||||
pos = current + ((PHYSFS_sint64) offset);
|
||||
} /* else if */
|
||||
|
||||
else if (whence == RW_SEEK_END)
|
||||
{
|
||||
const PHYSFS_sint64 len = PHYSFS_fileLength(handle);
|
||||
if (len == -1)
|
||||
{
|
||||
SDL_SetError("Can't find end of file: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
pos = len + ((PHYSFS_sint64) offset);
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
SDL_SetError("Invalid 'whence' parameter.");
|
||||
return -1;
|
||||
} /* else */
|
||||
|
||||
if ( pos < 0 )
|
||||
{
|
||||
SDL_SetError("Attempt to seek past start of file.");
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
#if TARGET_SDL2
|
||||
return (Sint64) pos;
|
||||
#else
|
||||
return (int) pos;
|
||||
#endif
|
||||
} /* physfsrwops_seek */
|
||||
|
||||
|
||||
#if TARGET_SDL2
|
||||
static size_t SDLCALL physfsrwops_read(struct SDL_RWops *rw, void *ptr,
|
||||
size_t size, size_t maxnum)
|
||||
#else
|
||||
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
|
||||
#endif
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
const PHYSFS_uint64 readlen = (PHYSFS_uint64) (maxnum * size);
|
||||
const PHYSFS_sint64 rc = PHYSFS_readBytes(handle, ptr, readlen);
|
||||
if (rc != ((PHYSFS_sint64) readlen))
|
||||
{
|
||||
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
|
||||
#if TARGET_SDL2
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
#if TARGET_SDL2
|
||||
return (size_t) rc / size;
|
||||
#else
|
||||
return (int) rc / size;
|
||||
#endif
|
||||
} /* physfsrwops_read */
|
||||
|
||||
|
||||
#if TARGET_SDL2
|
||||
static size_t SDLCALL physfsrwops_write(struct SDL_RWops *rw, const void *ptr,
|
||||
size_t size, size_t num)
|
||||
#else
|
||||
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
|
||||
#endif
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
const PHYSFS_uint64 writelen = (PHYSFS_uint64) (num * size);
|
||||
const PHYSFS_sint64 rc = PHYSFS_writeBytes(handle, ptr, writelen);
|
||||
if (rc != ((PHYSFS_sint64) writelen))
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
|
||||
#if TARGET_SDL2
|
||||
return (size_t) rc;
|
||||
#else
|
||||
return (int) rc;
|
||||
#endif
|
||||
} /* physfsrwops_write */
|
||||
|
||||
|
||||
static int physfsrwops_close(SDL_RWops *rw)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
if (!PHYSFS_close(handle))
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
SDL_FreeRW(rw);
|
||||
return 0;
|
||||
} /* physfsrwops_close */
|
||||
|
||||
|
||||
static SDL_RWops *create_rwops(PHYSFS_File *handle)
|
||||
{
|
||||
SDL_RWops *retval = NULL;
|
||||
|
||||
if (handle == NULL)
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
else
|
||||
{
|
||||
retval = SDL_AllocRW();
|
||||
if (retval != NULL)
|
||||
{
|
||||
#if TARGET_SDL2
|
||||
retval->size = physfsrwops_size;
|
||||
#endif
|
||||
retval->seek = physfsrwops_seek;
|
||||
retval->read = physfsrwops_read;
|
||||
retval->write = physfsrwops_write;
|
||||
retval->close = physfsrwops_close;
|
||||
retval->hidden.unknown.data1 = handle;
|
||||
} /* if */
|
||||
} /* else */
|
||||
|
||||
return retval;
|
||||
} /* create_rwops */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
|
||||
{
|
||||
SDL_RWops *retval = NULL;
|
||||
if (handle == NULL)
|
||||
SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops().");
|
||||
else
|
||||
retval = create_rwops(handle);
|
||||
|
||||
return retval;
|
||||
} /* PHYSFSRWOPS_makeRWops */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openRead(const char *fname)
|
||||
{
|
||||
return create_rwops(PHYSFS_openRead(fname));
|
||||
} /* PHYSFSRWOPS_openRead */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname)
|
||||
{
|
||||
return create_rwops(PHYSFS_openWrite(fname));
|
||||
} /* PHYSFSRWOPS_openWrite */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname)
|
||||
{
|
||||
return create_rwops(PHYSFS_openAppend(fname));
|
||||
} /* PHYSFSRWOPS_openAppend */
|
||||
|
||||
|
||||
/* end of physfsrwops.c ... */
|
||||
|
89
third-party/physfs/extras/physfsrwops.h
vendored
Normal file
89
third-party/physfs/extras/physfsrwops.h
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This code provides a glue layer between PhysicsFS and Simple Directmedia
|
||||
* Layer's (SDL) RWops i/o abstraction.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* SDL 1.2 falls under the LGPL license. SDL 1.3+ is zlib, like PhysicsFS.
|
||||
* You can get SDL at https://www.libsdl.org/
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_PHYSFSRWOPS_H_
|
||||
#define _INCLUDE_PHYSFSRWOPS_H_
|
||||
|
||||
#include "physfs.h"
|
||||
#include "SDL.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for reading, and make it accessible
|
||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
||||
* opening files through this method.
|
||||
*
|
||||
* @param filename File to open in platform-independent notation.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_openRead(const char *fname);
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for writing, and make it accessible
|
||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
||||
* opening files through this method.
|
||||
*
|
||||
* @param filename File to open in platform-independent notation.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname);
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for appending, and make it accessible
|
||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
||||
* opening files through this method.
|
||||
*
|
||||
* @param filename File to open in platform-independent notation.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname);
|
||||
|
||||
/**
|
||||
* Make a SDL_RWops from an existing PhysicsFS file handle. You should
|
||||
* dispose of any references to the handle after successful creation of
|
||||
* the RWops. The actual PhysicsFS handle will be destroyed when the
|
||||
* RWops is closed.
|
||||
*
|
||||
* @param handle a valid PhysicsFS file handle.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker */
|
||||
|
||||
/* end of physfsrwops.h ... */
|
||||
|
181
third-party/physfs/extras/physfsunpack.c
vendored
Normal file
181
third-party/physfs/extras/physfsunpack.c
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
|
||||
static int failure = 0;
|
||||
|
||||
static void modTimeToStr(PHYSFS_sint64 modtime, char *modstr, size_t strsize)
|
||||
{
|
||||
const char *str = "unknown modtime";
|
||||
if (modtime != -1)
|
||||
{
|
||||
time_t t = (time_t) modtime;
|
||||
str = ctime(&t);
|
||||
} /* if */
|
||||
|
||||
strncpy(modstr, str, strsize);
|
||||
modstr[strsize-1] = '\0';
|
||||
strsize = strlen(modstr);
|
||||
while ((modstr[strsize-1] == '\n') || (modstr[strsize-1] == '\r'))
|
||||
modstr[--strsize] = '\0';
|
||||
} /* modTimeToStr */
|
||||
|
||||
|
||||
static void fail(const char *what, const char *why)
|
||||
{
|
||||
if (why == NULL)
|
||||
why = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
|
||||
fprintf(stderr, "%s failed: %s\n", what, why);
|
||||
failure = 1;
|
||||
} /* fail */
|
||||
|
||||
|
||||
static void dumpFile(const char *fname)
|
||||
{
|
||||
const int origfailure = failure;
|
||||
PHYSFS_File *out = NULL;
|
||||
PHYSFS_File *in = NULL;
|
||||
|
||||
failure = 0;
|
||||
|
||||
if ((in = PHYSFS_openRead(fname)) == NULL)
|
||||
fail("\nPHYSFS_openRead", NULL);
|
||||
else if ((out = PHYSFS_openWrite(fname)) == NULL)
|
||||
fail("\nPHYSFS_openWrite", NULL);
|
||||
else
|
||||
{
|
||||
char modstr[64];
|
||||
PHYSFS_sint64 size = PHYSFS_fileLength(in);
|
||||
|
||||
printf("(");
|
||||
if (size == -1)
|
||||
printf("?");
|
||||
else
|
||||
printf("%lld", (long long) size);
|
||||
printf(" bytes");
|
||||
|
||||
modTimeToStr(PHYSFS_getLastModTime(fname), modstr, sizeof (modstr));
|
||||
printf(", %s)\n", modstr);
|
||||
|
||||
while ( (!failure) && (!PHYSFS_eof(in)) )
|
||||
{
|
||||
static char buf[64 * 1024];
|
||||
PHYSFS_sint64 br = PHYSFS_read(in, buf, 1, sizeof (buf));
|
||||
if (br == -1)
|
||||
fail("PHYSFS_read", NULL);
|
||||
else
|
||||
{
|
||||
PHYSFS_sint64 bw = PHYSFS_write(out, buf, 1, br);
|
||||
if (bw != br)
|
||||
fail("PHYSFS_write", NULL);
|
||||
else
|
||||
size -= bw;
|
||||
} /* else */
|
||||
} /* while */
|
||||
|
||||
if ((!failure) && (size != 0))
|
||||
fail("PHYSFS_eof", "BUG! eof != PHYSFS_fileLength bytes!");
|
||||
} /* else */
|
||||
|
||||
if (in != NULL)
|
||||
PHYSFS_close(in);
|
||||
|
||||
if (out != NULL)
|
||||
{
|
||||
if (!PHYSFS_close(out))
|
||||
fail("PHYSFS_close", NULL);
|
||||
} /* if */
|
||||
|
||||
if (failure)
|
||||
PHYSFS_delete(fname);
|
||||
else
|
||||
failure = origfailure;
|
||||
} /* dumpFile */
|
||||
|
||||
|
||||
static void unpackCallback(void *_depth, const char *origdir, const char *str)
|
||||
{
|
||||
int depth = *((int *) _depth);
|
||||
const int len = strlen(origdir) + strlen(str) + 2;
|
||||
char *fname = (char *) malloc(len);
|
||||
if (fname == NULL)
|
||||
fail("malloc", "Out of memory!");
|
||||
else
|
||||
{
|
||||
if (strcmp(origdir, "/") == 0)
|
||||
origdir = "";
|
||||
|
||||
snprintf(fname, len, "%s/%s", origdir, str);
|
||||
|
||||
printf("%s ", fname);
|
||||
if (PHYSFS_isDirectory(fname))
|
||||
{
|
||||
depth++;
|
||||
printf("(directory)\n");
|
||||
if (!PHYSFS_mkdir(fname))
|
||||
fail("PHYSFS_mkdir", NULL);
|
||||
else
|
||||
PHYSFS_enumerateFilesCallback(fname, unpackCallback, &depth);
|
||||
} /* if */
|
||||
|
||||
else if (PHYSFS_isSymbolicLink(fname))
|
||||
{
|
||||
printf("(symlink)\n");
|
||||
/* !!! FIXME: ? if (!symlink(fname, */
|
||||
} /* else if */
|
||||
|
||||
else /* ...file. */
|
||||
{
|
||||
dumpFile(fname);
|
||||
} /* else */
|
||||
|
||||
free(fname);
|
||||
} /* else */
|
||||
} /* unpackCallback */
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int zero = 0;
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
fprintf(stderr, "USAGE: %s <archive> <unpackDirectory>\n", argv[0]);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_init() failed: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 2;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_setWriteDir(argv[2]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_setWriteDir('%s') failed: %s\n",
|
||||
argv[2], PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 3;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_mount(argv[1], NULL, 1))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_mount('%s') failed: %s\n",
|
||||
argv[1], PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 4;
|
||||
} /* if */
|
||||
|
||||
PHYSFS_permitSymbolicLinks(1);
|
||||
PHYSFS_enumerateFilesCallback("/", unpackCallback, &zero);
|
||||
PHYSFS_deinit();
|
||||
if (failure)
|
||||
return 5;
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
/* end of physfsunpack.c ... */
|
||||
|
66
third-party/physfs/extras/selfextract.c
vendored
Normal file
66
third-party/physfs/extras/selfextract.c
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This code shows how to read a zipfile included in an app's binary.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compile this program and then attach a .zip file to the end of the
|
||||
* compiled binary.
|
||||
*
|
||||
* On Linux, something like this will build the final binary:
|
||||
* gcc -o selfextract.tmp selfextract.c -lphysfs && \
|
||||
* cat selfextract.tmp myzipfile.zip >> selfextract && \
|
||||
* chmod a+x selfextract && \
|
||||
* rm -f selfextract.tmp
|
||||
*
|
||||
* This may not work on all platforms, and it probably only works with
|
||||
* .zip files, since they are designed to be appended to another file.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "physfs.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
printf("PHYSFS_init() failed: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
rc = PHYSFS_addToSearchPath(argv[0], 0);
|
||||
if (!rc)
|
||||
{
|
||||
printf("Couldn't find self-extract data: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
printf("This might mean you didn't append a zipfile to the binary.\n");
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
char **files = PHYSFS_enumerateFiles("/");
|
||||
char **i;
|
||||
for (i = files; *i != NULL; i++)
|
||||
{
|
||||
const char *dirorfile = PHYSFS_isDirectory(*i) ? "Directory" : "File";
|
||||
printf(" * %s '%s' is in root of attached data.\n", dirorfile, *i);
|
||||
} /* for */
|
||||
PHYSFS_freeList(files);
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
|
10
third-party/physfs/extras/uninstall.sh
vendored
Normal file
10
third-party/physfs/extras/uninstall.sh
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -f "./install_manifest.txt" ]; then
|
||||
echo "ERROR: This needs to be run from your CMake build directory after installing." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
xargs rm -vf < install_manifest.txt
|
||||
exit 0
|
||||
|
Reference in New Issue
Block a user