PhysicsFS 2.0.3 imported.
This commit is contained in:
parent
bcc0937726
commit
993311d151
459 changed files with 87785 additions and 0 deletions
256
lib/physfs-2.0.3/platform/beos.cpp
Normal file
256
lib/physfs-2.0.3/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 */
|
||||
|
||||
|
||||
void *__PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return((void *) 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 ... */
|
||||
|
419
lib/physfs-2.0.3/platform/macosx.c
Normal file
419
lib/physfs-2.0.3/platform/macosx.c
Normal file
|
@ -0,0 +1,419 @@
|
|||
/*
|
||||
* 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>
|
||||
#include <sys/stat.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 };
|
||||
struct stat statbuf;
|
||||
FSRef fsref;
|
||||
CFRange cfrange;
|
||||
CFURLRef cfurl = NULL;
|
||||
CFStringRef cfstr = NULL;
|
||||
CFMutableStringRef cfmutstr = NULL;
|
||||
char *retval = NULL;
|
||||
char *cstr = NULL;
|
||||
int rc = 0;
|
||||
|
||||
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);
|
||||
|
||||
/* we have to decide if we got a binary's path, or the .app dir... */
|
||||
cstr = convertCFString(cfmutstr);
|
||||
if (cstr == NULL)
|
||||
{
|
||||
CFRelease(cfmutstr);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
rc = stat(cstr, &statbuf);
|
||||
allocator.Free(cstr); /* done with this. */
|
||||
if (rc == -1)
|
||||
{
|
||||
CFRelease(cfmutstr);
|
||||
return(NULL); /* maybe default behaviour will work? */
|
||||
} /* if */
|
||||
|
||||
if (S_ISREG(statbuf.st_mode))
|
||||
{
|
||||
/* Find last dirsep so we can chop the 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. */
|
||||
} /* if */
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
void *__PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return( (void *) ((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
lib/physfs-2.0.3/platform/os2.c
Normal file
702
lib/physfs-2.0.3/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 */
|
||||
|
||||
|
||||
void *__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((void *) 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 ... */
|
||||
|
612
lib/physfs-2.0.3/platform/pocketpc.c
Normal file
612
lib/physfs-2.0.3/platform/pocketpc.c
Normal file
|
@ -0,0 +1,612 @@
|
|||
/*
|
||||
* 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 */
|
||||
|
||||
|
||||
void *__PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return((void *)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(), -1);
|
||||
} /* 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)
|
||||
{
|
||||
const PHYSFS_sint64 FileLength = __PHYSFS_platformFileLength(opaque);
|
||||
PHYSFS_sint64 FilePosition;
|
||||
int retval = 0;
|
||||
|
||||
if (FileLength == 0)
|
||||
return 1; /* we're definitely at EOF. */
|
||||
|
||||
/* Get the current position in the file */
|
||||
if ((FilePosition = __PHYSFS_platformTell(opaque)) != -1)
|
||||
{
|
||||
/* Non-zero if EOF is equal to the file length */
|
||||
retval = (FilePosition == FileLength);
|
||||
} /* 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
lib/physfs-2.0.3/platform/posix.c
Normal file
424
lib/physfs-2.0.3/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 < 0) || (len < 0) || (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 ... */
|
||||
|
431
lib/physfs-2.0.3/platform/unix.c
Normal file
431
lib/physfs-2.0.3/platform/unix.c
Normal file
|
@ -0,0 +1,431 @@
|
|||
/*
|
||||
* 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)
|
||||
|
||||
void *__PHYSFS_platformGetThreadID(void) { return((void *) 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;
|
||||
|
||||
void *__PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return( (void *) ((size_t) 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 ... */
|
||||
|
1408
lib/physfs-2.0.3/platform/windows.c
Normal file
1408
lib/physfs-2.0.3/platform/windows.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue