initial commit
This commit is contained in:
396
physfs/platform/macosx.c
Normal file
396
physfs/platform/macosx.c
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Mac OS X support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_platforms.h"
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_MACOSX
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <IOKit/storage/IOMedia.h>
|
||||
#include <IOKit/storage/IOCDMedia.h>
|
||||
#include <IOKit/storage/IODVDMedia.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
/* Seems to get defined in some system header... */
|
||||
#ifdef Free
|
||||
#undef Free
|
||||
#endif
|
||||
|
||||
#include "physfs_internal.h"
|
||||
|
||||
|
||||
/* Wrap PHYSFS_Allocator in a CFAllocator... */
|
||||
static CFAllocatorRef cfallocator = NULL;
|
||||
|
||||
CFStringRef cfallocDesc(const void *info)
|
||||
{
|
||||
return(CFStringCreateWithCString(cfallocator, "PhysicsFS",
|
||||
kCFStringEncodingASCII));
|
||||
} /* cfallocDesc */
|
||||
|
||||
|
||||
static void *cfallocMalloc(CFIndex allocSize, CFOptionFlags hint, void *info)
|
||||
{
|
||||
return allocator.Malloc(allocSize);
|
||||
} /* cfallocMalloc */
|
||||
|
||||
|
||||
static void cfallocFree(void *ptr, void *info)
|
||||
{
|
||||
allocator.Free(ptr);
|
||||
} /* cfallocFree */
|
||||
|
||||
|
||||
static void *cfallocRealloc(void *ptr, CFIndex newsize,
|
||||
CFOptionFlags hint, void *info)
|
||||
{
|
||||
if ((ptr == NULL) || (newsize <= 0))
|
||||
return NULL; /* ADC docs say you should always return NULL here. */
|
||||
return allocator.Realloc(ptr, newsize);
|
||||
} /* cfallocRealloc */
|
||||
|
||||
|
||||
int __PHYSFS_platformInit(void)
|
||||
{
|
||||
/* set up a CFAllocator, so Carbon can use the physfs allocator, too. */
|
||||
CFAllocatorContext ctx;
|
||||
memset(&ctx, '\0', sizeof (ctx));
|
||||
ctx.copyDescription = cfallocDesc;
|
||||
ctx.allocate = cfallocMalloc;
|
||||
ctx.reallocate = cfallocRealloc;
|
||||
ctx.deallocate = cfallocFree;
|
||||
cfallocator = CFAllocatorCreate(kCFAllocatorUseContext, &ctx);
|
||||
BAIL_IF_MACRO(cfallocator == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
return(1); /* success. */
|
||||
} /* __PHYSFS_platformInit */
|
||||
|
||||
|
||||
int __PHYSFS_platformDeinit(void)
|
||||
{
|
||||
CFRelease(cfallocator);
|
||||
cfallocator = NULL;
|
||||
return(1); /* always succeed. */
|
||||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
/* CD-ROM detection code... */
|
||||
|
||||
/*
|
||||
* Code based on sample from Apple Developer Connection:
|
||||
* http://developer.apple.com/samplecode/Sample_Code/Devices_and_Hardware/Disks/VolumeToBSDNode/VolumeToBSDNode.c.htm
|
||||
*/
|
||||
|
||||
static int darwinIsWholeMedia(io_service_t service)
|
||||
{
|
||||
int retval = 0;
|
||||
CFTypeRef wholeMedia;
|
||||
|
||||
if (!IOObjectConformsTo(service, kIOMediaClass))
|
||||
return(0);
|
||||
|
||||
wholeMedia = IORegistryEntryCreateCFProperty(service,
|
||||
CFSTR(kIOMediaWholeKey),
|
||||
cfallocator, 0);
|
||||
if (wholeMedia == NULL)
|
||||
return(0);
|
||||
|
||||
retval = CFBooleanGetValue(wholeMedia);
|
||||
CFRelease(wholeMedia);
|
||||
|
||||
return retval;
|
||||
} /* darwinIsWholeMedia */
|
||||
|
||||
|
||||
static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
|
||||
{
|
||||
int retval = 0;
|
||||
CFMutableDictionaryRef matchingDict;
|
||||
kern_return_t rc;
|
||||
io_iterator_t iter;
|
||||
io_service_t service;
|
||||
|
||||
if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL)
|
||||
return(0);
|
||||
|
||||
rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter);
|
||||
if ((rc != KERN_SUCCESS) || (!iter))
|
||||
return(0);
|
||||
|
||||
service = IOIteratorNext(iter);
|
||||
IOObjectRelease(iter);
|
||||
if (!service)
|
||||
return(0);
|
||||
|
||||
rc = IORegistryEntryCreateIterator(service, kIOServicePlane,
|
||||
kIORegistryIterateRecursively | kIORegistryIterateParents, &iter);
|
||||
|
||||
if (!iter)
|
||||
return(0);
|
||||
|
||||
if (rc != KERN_SUCCESS)
|
||||
{
|
||||
IOObjectRelease(iter);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
IOObjectRetain(service); /* add an extra object reference... */
|
||||
|
||||
do
|
||||
{
|
||||
if (darwinIsWholeMedia(service))
|
||||
{
|
||||
if ( (IOObjectConformsTo(service, kIOCDMediaClass)) ||
|
||||
(IOObjectConformsTo(service, kIODVDMediaClass)) )
|
||||
{
|
||||
retval = 1;
|
||||
} /* if */
|
||||
} /* if */
|
||||
IOObjectRelease(service);
|
||||
} while ((service = IOIteratorNext(iter)) && (!retval));
|
||||
|
||||
IOObjectRelease(iter);
|
||||
IOObjectRelease(service);
|
||||
|
||||
return(retval);
|
||||
} /* darwinIsMountedDisc */
|
||||
|
||||
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
const char *devPrefix = "/dev/";
|
||||
const int prefixLen = strlen(devPrefix);
|
||||
mach_port_t masterPort = 0;
|
||||
struct statfs *mntbufp;
|
||||
int i, mounts;
|
||||
|
||||
if (IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS)
|
||||
BAIL_MACRO(ERR_OS_ERROR, ) /*return void*/;
|
||||
|
||||
mounts = getmntinfo(&mntbufp, MNT_WAIT); /* NOT THREAD SAFE! */
|
||||
for (i = 0; i < mounts; i++)
|
||||
{
|
||||
char *dev = mntbufp[i].f_mntfromname;
|
||||
char *mnt = mntbufp[i].f_mntonname;
|
||||
if (strncmp(dev, devPrefix, prefixLen) != 0) /* a virtual device? */
|
||||
continue;
|
||||
|
||||
dev += prefixLen;
|
||||
if (darwinIsMountedDisc(dev, masterPort))
|
||||
cb(data, mnt);
|
||||
} /* for */
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
static char *convertCFString(CFStringRef cfstr)
|
||||
{
|
||||
CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr),
|
||||
kCFStringEncodingUTF8) + 1;
|
||||
char *retval = (char *) allocator.Malloc(len);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
if (CFStringGetCString(cfstr, retval, len, kCFStringEncodingUTF8))
|
||||
{
|
||||
/* shrink overallocated buffer if possible... */
|
||||
CFIndex newlen = strlen(retval) + 1;
|
||||
if (newlen < len)
|
||||
{
|
||||
void *ptr = allocator.Realloc(retval, newlen);
|
||||
if (ptr != NULL)
|
||||
retval = (char *) ptr;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
else /* probably shouldn't fail, but just in case... */
|
||||
{
|
||||
allocator.Free(retval);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
} /* convertCFString */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
{
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||
FSRef fsref;
|
||||
CFRange cfrange;
|
||||
CFURLRef cfurl = NULL;
|
||||
CFStringRef cfstr = NULL;
|
||||
CFMutableStringRef cfmutstr = NULL;
|
||||
char *retval = NULL;
|
||||
|
||||
BAIL_IF_MACRO(GetProcessBundleLocation(&psn, &fsref) != noErr, NULL, NULL);
|
||||
cfurl = CFURLCreateFromFSRef(cfallocator, &fsref);
|
||||
BAIL_IF_MACRO(cfurl == NULL, NULL, NULL);
|
||||
cfstr = CFURLCopyFileSystemPath(cfurl, kCFURLPOSIXPathStyle);
|
||||
CFRelease(cfurl);
|
||||
BAIL_IF_MACRO(cfstr == NULL, NULL, NULL);
|
||||
cfmutstr = CFStringCreateMutableCopy(cfallocator, 0, cfstr);
|
||||
CFRelease(cfstr);
|
||||
BAIL_IF_MACRO(cfmutstr == NULL, NULL, NULL);
|
||||
|
||||
/* Find last dirsep so we can chop the binary's filename from the path. */
|
||||
cfrange = CFStringFind(cfmutstr, CFSTR("/"), kCFCompareBackwards);
|
||||
if (cfrange.location == kCFNotFound)
|
||||
{
|
||||
assert(0); /* shouldn't ever hit this... */
|
||||
CFRelease(cfmutstr);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
/* chop the "/exename" from the end of the path string... */
|
||||
cfrange.length = CFStringGetLength(cfmutstr) - cfrange.location;
|
||||
CFStringDelete(cfmutstr, cfrange);
|
||||
|
||||
/* If we're an Application Bundle, chop everything but the base. */
|
||||
cfrange = CFStringFind(cfmutstr, CFSTR("/Contents/MacOS"),
|
||||
kCFCompareCaseInsensitive |
|
||||
kCFCompareBackwards |
|
||||
kCFCompareAnchored);
|
||||
|
||||
if (cfrange.location != kCFNotFound)
|
||||
CFStringDelete(cfmutstr, cfrange); /* chop that, too. */
|
||||
|
||||
retval = convertCFString(cfmutstr);
|
||||
CFRelease(cfmutstr);
|
||||
|
||||
return(retval); /* whew. */
|
||||
} /* __PHYSFS_platformCalcBaseDir */
|
||||
|
||||
|
||||
/* !!! FIXME */
|
||||
#define osxerr(x) x
|
||||
|
||||
char *__PHYSFS_platformRealPath(const char *path)
|
||||
{
|
||||
/* The symlink and relative path resolving happens in FSPathMakeRef() */
|
||||
FSRef fsref;
|
||||
CFURLRef cfurl = NULL;
|
||||
CFStringRef cfstr = NULL;
|
||||
char *retval = NULL;
|
||||
OSStatus rc = osxerr(FSPathMakeRef((UInt8 *) path, &fsref, NULL));
|
||||
BAIL_IF_MACRO(rc != noErr, NULL, NULL);
|
||||
|
||||
/* Now get it to spit out a full path. */
|
||||
cfurl = CFURLCreateFromFSRef(cfallocator, &fsref);
|
||||
BAIL_IF_MACRO(cfurl == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
cfstr = CFURLCopyFileSystemPath(cfurl, kCFURLPOSIXPathStyle);
|
||||
CFRelease(cfurl);
|
||||
BAIL_IF_MACRO(cfstr == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
retval = convertCFString(cfstr);
|
||||
CFRelease(cfstr);
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformRealPath */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCurrentDir(void)
|
||||
{
|
||||
return(__PHYSFS_platformRealPath(".")); /* let CFURL sort it out. */
|
||||
} /* __PHYSFS_platformCurrentDir */
|
||||
|
||||
|
||||
/* Platform allocator uses default CFAllocator at PHYSFS_init() time. */
|
||||
|
||||
static CFAllocatorRef cfallocdef = NULL;
|
||||
|
||||
static int macosxAllocatorInit(void)
|
||||
{
|
||||
int retval = 0;
|
||||
cfallocdef = CFAllocatorGetDefault();
|
||||
retval = (cfallocdef != NULL);
|
||||
if (retval)
|
||||
CFRetain(cfallocdef);
|
||||
return(retval);
|
||||
} /* macosxAllocatorInit */
|
||||
|
||||
|
||||
static void macosxAllocatorDeinit(void)
|
||||
{
|
||||
if (cfallocdef != NULL)
|
||||
{
|
||||
CFRelease(cfallocdef);
|
||||
cfallocdef = NULL;
|
||||
} /* if */
|
||||
} /* macosxAllocatorDeinit */
|
||||
|
||||
|
||||
static void *macosxAllocatorMalloc(PHYSFS_uint64 s)
|
||||
{
|
||||
BAIL_IF_MACRO(__PHYSFS_ui64FitsAddressSpace(s), ERR_OUT_OF_MEMORY, NULL);
|
||||
return(CFAllocatorAllocate(cfallocdef, (CFIndex) s, 0));
|
||||
} /* macosxAllocatorMalloc */
|
||||
|
||||
|
||||
static void *macosxAllocatorRealloc(void *ptr, PHYSFS_uint64 s)
|
||||
{
|
||||
BAIL_IF_MACRO(__PHYSFS_ui64FitsAddressSpace(s), ERR_OUT_OF_MEMORY, NULL);
|
||||
return(CFAllocatorReallocate(cfallocdef, ptr, (CFIndex) s, 0));
|
||||
} /* macosxAllocatorRealloc */
|
||||
|
||||
|
||||
static void macosxAllocatorFree(void *ptr)
|
||||
{
|
||||
CFAllocatorDeallocate(cfallocdef, ptr);
|
||||
} /* macosxAllocatorFree */
|
||||
|
||||
|
||||
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
|
||||
{
|
||||
allocator.Init = macosxAllocatorInit;
|
||||
allocator.Deinit = macosxAllocatorDeinit;
|
||||
allocator.Malloc = macosxAllocatorMalloc;
|
||||
allocator.Realloc = macosxAllocatorRealloc;
|
||||
allocator.Free = macosxAllocatorFree;
|
||||
return(1); /* return non-zero: we're supplying custom allocator. */
|
||||
} /* __PHYSFS_platformSetDefaultAllocator */
|
||||
|
||||
|
||||
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return( (PHYSFS_uint64) ((size_t) MPCurrentTaskID()) );
|
||||
} /* __PHYSFS_platformGetThreadID */
|
||||
|
||||
|
||||
void *__PHYSFS_platformCreateMutex(void)
|
||||
{
|
||||
MPCriticalRegionID m = NULL;
|
||||
if (osxerr(MPCreateCriticalRegion(&m)) != noErr)
|
||||
return NULL;
|
||||
return m;
|
||||
} /* __PHYSFS_platformCreateMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformDestroyMutex(void *mutex)
|
||||
{
|
||||
MPCriticalRegionID m = (MPCriticalRegionID) mutex;
|
||||
MPDeleteCriticalRegion(m);
|
||||
} /* __PHYSFS_platformDestroyMutex */
|
||||
|
||||
|
||||
int __PHYSFS_platformGrabMutex(void *mutex)
|
||||
{
|
||||
MPCriticalRegionID m = (MPCriticalRegionID) mutex;
|
||||
if (MPEnterCriticalRegion(m, kDurationForever) != noErr)
|
||||
return(0);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformGrabMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex)
|
||||
{
|
||||
MPCriticalRegionID m = (MPCriticalRegionID) mutex;
|
||||
MPExitCriticalRegion(m);
|
||||
} /* __PHYSFS_platformReleaseMutex */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_MACOSX */
|
||||
|
||||
/* end of macosx.c ... */
|
||||
|
404
physfs/platform/posix.c
Normal file
404
physfs/platform/posix.c
Normal file
@ -0,0 +1,404 @@
|
||||
/*
|
||||
* 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 (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)
|
||||
{
|
||||
int fd;
|
||||
int *retval;
|
||||
errno = 0;
|
||||
|
||||
fd = open(filename, mode, S_IRUSR | S_IWUSR);
|
||||
BAIL_IF_MACRO(fd < 0, strerror(errno), NULL);
|
||||
|
||||
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);
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
BAIL_IF_MACRO(rc == -1, strerror(errno), rc);
|
||||
assert(rc <= max);
|
||||
|
||||
if ((rc < max) && (size > 1))
|
||||
lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */
|
||||
|
||||
return (rc / size);
|
||||
} /* __PHYSFS_platformRead */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
|
||||
PHYSFS_uint32 size, PHYSFS_uint32 count)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
int max = size * count;
|
||||
int rc = write(fd, (void *) buffer, max);
|
||||
|
||||
BAIL_IF_MACRO(rc == -1, strerror(errno), rc);
|
||||
assert(rc <= max);
|
||||
|
||||
if ((rc < max) && (size > 1))
|
||||
lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */
|
||||
|
||||
return(rc / size);
|
||||
} /* __PHYSFS_platformWrite */
|
||||
|
||||
|
||||
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
|
||||
#ifdef PHYSFS_HAVE_LLSEEK
|
||||
unsigned long offset_high = ((pos >> 32) & 0xFFFFFFFF);
|
||||
unsigned long offset_low = (pos & 0xFFFFFFFF);
|
||||
loff_t retoffset;
|
||||
int rc = llseek(fd, offset_high, offset_low, &retoffset, SEEK_SET);
|
||||
BAIL_IF_MACRO(rc == -1, strerror(errno), 0);
|
||||
#else
|
||||
BAIL_IF_MACRO(lseek(fd, (int) pos, SEEK_SET) == -1, strerror(errno), 0);
|
||||
#endif
|
||||
|
||||
return(1);
|
||||
} /* __PHYSFS_platformSeek */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
PHYSFS_sint64 retval;
|
||||
|
||||
#ifdef PHYSFS_HAVE_LLSEEK
|
||||
loff_t retoffset;
|
||||
int rc = llseek(fd, 0, &retoffset, SEEK_CUR);
|
||||
BAIL_IF_MACRO(rc == -1, strerror(errno), -1);
|
||||
retval = (PHYSFS_sint64) retoffset;
|
||||
#else
|
||||
retval = (PHYSFS_sint64) lseek(fd, 0, SEEK_CUR);
|
||||
BAIL_IF_MACRO(retval == -1, strerror(errno), -1);
|
||||
#endif
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformTell */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
struct stat statbuf;
|
||||
BAIL_IF_MACRO(fstat(fd, &statbuf) == -1, strerror(errno), -1);
|
||||
return((PHYSFS_sint64) statbuf.st_size);
|
||||
} /* __PHYSFS_platformFileLength */
|
||||
|
||||
|
||||
int __PHYSFS_platformEOF(void *opaque)
|
||||
{
|
||||
PHYSFS_sint64 pos = __PHYSFS_platformTell(opaque);
|
||||
PHYSFS_sint64 len = __PHYSFS_platformFileLength(opaque);
|
||||
return(pos >= len);
|
||||
} /* __PHYSFS_platformEOF */
|
||||
|
||||
|
||||
int __PHYSFS_platformFlush(void *opaque)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
BAIL_IF_MACRO(fsync(fd) == -1, strerror(errno), 0);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformFlush */
|
||||
|
||||
|
||||
int __PHYSFS_platformClose(void *opaque)
|
||||
{
|
||||
int fd = *((int *) opaque);
|
||||
BAIL_IF_MACRO(close(fd) == -1, strerror(errno), 0);
|
||||
allocator.Free(opaque);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformClose */
|
||||
|
||||
|
||||
int __PHYSFS_platformDelete(const char *path)
|
||||
{
|
||||
BAIL_IF_MACRO(remove(path) == -1, strerror(errno), 0);
|
||||
return(1);
|
||||
} /* __PHYSFS_platformDelete */
|
||||
|
||||
|
||||
PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
|
||||
{
|
||||
struct stat statbuf;
|
||||
BAIL_IF_MACRO(stat(fname, &statbuf) < 0, strerror(errno), -1);
|
||||
return statbuf.st_mtime;
|
||||
} /* __PHYSFS_platformGetLastModTime */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_POSIX */
|
||||
|
||||
/* end of posix.c ... */
|
||||
|
395
physfs/platform/unix.c
Normal file
395
physfs/platform/unix.c
Normal file
@ -0,0 +1,395 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#if (!defined PHYSFS_NO_PTHREADS_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>
|
||||
#endif
|
||||
|
||||
#ifdef PHYSFS_HAVE_MNTENT_H
|
||||
#include <mntent.h>
|
||||
#endif
|
||||
|
||||
#include "physfs_internal.h"
|
||||
|
||||
|
||||
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;
|
||||
|
||||
/* 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 */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
{
|
||||
const char *PROC_SELF_EXE = "/proc/self/exe";
|
||||
char *retval = NULL;
|
||||
char *envr = NULL;
|
||||
struct stat stbuf;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
if ((lstat(PROC_SELF_EXE, &stbuf) != -1) && (S_ISLNK(stbuf.st_mode)))
|
||||
{
|
||||
const size_t len = stbuf.st_size;
|
||||
char *buf = (char *) allocator.Malloc(len+1);
|
||||
if (buf != NULL) /* if NULL, maybe you'll get lucky later. */
|
||||
{
|
||||
if (readlink(PROC_SELF_EXE, buf, len) != len)
|
||||
allocator.Free(buf);
|
||||
else
|
||||
{
|
||||
buf[len] = '\0'; /* readlink doesn't null-terminate. */
|
||||
retval = buf; /* we're good to go. */
|
||||
} /* else */
|
||||
} /* if */
|
||||
} /* 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 */
|
||||
|
||||
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_PTHREADS_SUPPORT)
|
||||
|
||||
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void) { return(0x0001); }
|
||||
void *__PHYSFS_platformCreateMutex(void) { return((void *) 0x0001); }
|
||||
void __PHYSFS_platformDestroyMutex(void *mutex) {}
|
||||
int __PHYSFS_platformGrabMutex(void *mutex) { return(1); }
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex) {}
|
||||
|
||||
#else
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
pthread_t owner;
|
||||
PHYSFS_uint32 count;
|
||||
} PthreadMutex;
|
||||
|
||||
/* Just in case; this is a panic value. */
|
||||
#if ((!defined SIZEOF_INT) || (SIZEOF_INT <= 0))
|
||||
# define SIZEOF_INT 4
|
||||
#endif
|
||||
|
||||
#if (SIZEOF_INT == 4)
|
||||
# define PHTREAD_TO_UI64(thr) ( (PHYSFS_uint64) ((PHYSFS_uint32) (thr)) )
|
||||
#elif (SIZEOF_INT == 2)
|
||||
# define PHTREAD_TO_UI64(thr) ( (PHYSFS_uint64) ((PHYSFS_uint16) (thr)) )
|
||||
#elif (SIZEOF_INT == 1)
|
||||
# define PHTREAD_TO_UI64(thr) ( (PHYSFS_uint64) ((PHYSFS_uint8) (thr)) )
|
||||
#else
|
||||
# define PHTREAD_TO_UI64(thr) ((PHYSFS_uint64) (thr))
|
||||
#endif
|
||||
|
||||
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return(PHTREAD_TO_UI64(pthread_self()));
|
||||
} /* __PHYSFS_platformGetThreadID */
|
||||
|
||||
|
||||
void *__PHYSFS_platformCreateMutex(void)
|
||||
{
|
||||
int rc;
|
||||
PthreadMutex *m = (PthreadMutex *) allocator.Malloc(sizeof (PthreadMutex));
|
||||
BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
rc = pthread_mutex_init(&m->mutex, NULL);
|
||||
if (rc != 0)
|
||||
{
|
||||
allocator.Free(m);
|
||||
BAIL_MACRO(strerror(rc), NULL);
|
||||
} /* if */
|
||||
|
||||
m->count = 0;
|
||||
m->owner = (pthread_t) 0xDEADBEEF;
|
||||
return((void *) m);
|
||||
} /* __PHYSFS_platformCreateMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformDestroyMutex(void *mutex)
|
||||
{
|
||||
PthreadMutex *m = (PthreadMutex *) mutex;
|
||||
|
||||
/* Destroying a locked mutex is a bug, but we'll try to be helpful. */
|
||||
if ((m->owner == pthread_self()) && (m->count > 0))
|
||||
pthread_mutex_unlock(&m->mutex);
|
||||
|
||||
pthread_mutex_destroy(&m->mutex);
|
||||
allocator.Free(m);
|
||||
} /* __PHYSFS_platformDestroyMutex */
|
||||
|
||||
|
||||
int __PHYSFS_platformGrabMutex(void *mutex)
|
||||
{
|
||||
PthreadMutex *m = (PthreadMutex *) mutex;
|
||||
pthread_t tid = pthread_self();
|
||||
if (m->owner != tid)
|
||||
{
|
||||
if (pthread_mutex_lock(&m->mutex) != 0)
|
||||
return(0);
|
||||
m->owner = tid;
|
||||
} /* if */
|
||||
|
||||
m->count++;
|
||||
return(1);
|
||||
} /* __PHYSFS_platformGrabMutex */
|
||||
|
||||
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex)
|
||||
{
|
||||
PthreadMutex *m = (PthreadMutex *) mutex;
|
||||
if (m->owner == pthread_self())
|
||||
{
|
||||
if (--m->count == 0)
|
||||
{
|
||||
m->owner = (pthread_t) 0xDEADBEEF;
|
||||
pthread_mutex_unlock(&m->mutex);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* __PHYSFS_platformReleaseMutex */
|
||||
|
||||
#endif /* !PHYSFS_NO_PTHREADS_SUPPORT */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_UNIX */
|
||||
|
||||
/* end of unix.c ... */
|
||||
|
1395
physfs/platform/windows.c
Normal file
1395
physfs/platform/windows.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user