Split out Mac OS X code from unix.c and added some Carbon-specific code...
moved some stuff around and implemented a few things in BeOS and POSIX bits to accomodate this.
This commit is contained in:
parent
03fe5bb823
commit
075e6769e2
|
@ -117,6 +117,7 @@ SET(PHYSFS_SRCS
|
||||||
platform/pocketpc.c
|
platform/pocketpc.c
|
||||||
platform/posix.c
|
platform/posix.c
|
||||||
platform/unix.c
|
platform/unix.c
|
||||||
|
platform/macosx.c
|
||||||
platform/windows.c
|
platform/windows.c
|
||||||
archivers/dir.c
|
archivers/dir.c
|
||||||
archivers/grp.c
|
archivers/grp.c
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
# define PHYSFS_PLATFORM_OS2
|
# define PHYSFS_PLATFORM_OS2
|
||||||
#elif ((defined __MACH__) && (defined __APPLE__))
|
#elif ((defined __MACH__) && (defined __APPLE__))
|
||||||
# define PHYSFS_PLATFORM_MACOSX
|
# define PHYSFS_PLATFORM_MACOSX
|
||||||
# define PHYSFS_PLATFORM_UNIX
|
|
||||||
# define PHYSFS_PLATFORM_POSIX
|
# define PHYSFS_PLATFORM_POSIX
|
||||||
#elif defined(macintosh)
|
#elif defined(macintosh)
|
||||||
# error Classic Mac OS support was dropped from PhysicsFS 2.0. Move to OS X.
|
# error Classic Mac OS support was dropped from PhysicsFS 2.0. Move to OS X.
|
||||||
|
|
|
@ -30,9 +30,6 @@
|
||||||
#include "physfs_internal.h"
|
#include "physfs_internal.h"
|
||||||
|
|
||||||
|
|
||||||
const char *__PHYSFS_platformDirSeparator = "/";
|
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformInit(void)
|
int __PHYSFS_platformInit(void)
|
||||||
{
|
{
|
||||||
return(1); /* always succeed. */
|
return(1); /* always succeed. */
|
||||||
|
@ -158,7 +155,7 @@ static team_id getTeamID(void)
|
||||||
thread_id tid = find_thread(NULL);
|
thread_id tid = find_thread(NULL);
|
||||||
get_thread_info(tid, &info);
|
get_thread_info(tid, &info);
|
||||||
return(info.team);
|
return(info.team);
|
||||||
} /* getMyTeamID */
|
} /* getTeamID */
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||||
|
@ -201,6 +198,12 @@ char *__PHYSFS_platformRealPath(const char *path)
|
||||||
} /* __PHYSFS_platformRealPath */
|
} /* __PHYSFS_platformRealPath */
|
||||||
|
|
||||||
|
|
||||||
|
char *__PHYSFS_platformCurrentDir(void)
|
||||||
|
{
|
||||||
|
return(__PHYSFS_platformRealPath(".")); /* let BPath sort it out. */
|
||||||
|
} /* __PHYSFS_platformCurrentDir */
|
||||||
|
|
||||||
|
|
||||||
/* !!! FIXME: semaphores are not mutexes... */
|
/* !!! FIXME: semaphores are not mutexes... */
|
||||||
void *__PHYSFS_platformCreateMutex(void)
|
void *__PHYSFS_platformCreateMutex(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 ... */
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
#include "physfs_internal.h"
|
#include "physfs_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char *__PHYSFS_platformDirSeparator = "/";
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname)
|
char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname)
|
||||||
{
|
{
|
||||||
const char *envr = getenv(varname);
|
const char *envr = getenv(varname);
|
||||||
|
@ -224,43 +227,6 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||||
} /* __PHYSFS_platformEnumerateFiles */
|
} /* __PHYSFS_platformEnumerateFiles */
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCurrentDir(void)
|
|
||||||
{
|
|
||||||
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_platformMkDir(const char *path)
|
int __PHYSFS_platformMkDir(const char *path)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
270
platform/unix.c
270
platform/unix.c
|
@ -25,15 +25,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
|
||||||
#ifdef PHYSFS_PLATFORM_MACOSX
|
|
||||||
# include <CoreFoundation/CoreFoundation.h>
|
|
||||||
# include <CoreServices/CoreServices.h>
|
|
||||||
# include <IOKit/IOKitLib.h>
|
|
||||||
# include <IOKit/storage/IOMedia.h>
|
|
||||||
# include <IOKit/storage/IOCDMedia.h>
|
|
||||||
# include <IOKit/storage/IODVDMedia.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (!defined PHYSFS_NO_PTHREADS_SUPPORT)
|
#if (!defined PHYSFS_NO_PTHREADS_SUPPORT)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,13 +42,6 @@
|
||||||
|
|
||||||
#include "physfs_internal.h"
|
#include "physfs_internal.h"
|
||||||
|
|
||||||
/* Seems to get defined in some system header... */
|
|
||||||
#ifdef Free
|
|
||||||
#undef Free
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *__PHYSFS_platformDirSeparator = "/";
|
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformInit(void)
|
int __PHYSFS_platformInit(void)
|
||||||
{
|
{
|
||||||
|
@ -78,113 +62,6 @@ void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||||
{
|
{
|
||||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||||
|
|
||||||
|
|
||||||
#elif (defined PHYSFS_PLATFORM_MACOSX) /* "Big Nasty." */
|
|
||||||
/*
|
|
||||||
* 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),
|
|
||||||
kCFAllocatorDefault, 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/";
|
|
||||||
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 */
|
|
||||||
|
|
||||||
#elif (defined PHYSFS_HAVE_SYS_UCRED_H)
|
#elif (defined PHYSFS_HAVE_SYS_UCRED_H)
|
||||||
|
|
||||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||||
|
@ -350,107 +227,6 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||||
} /* __PHYSFS_platformCalcBaseDir */
|
} /* __PHYSFS_platformCalcBaseDir */
|
||||||
|
|
||||||
|
|
||||||
#ifdef PHYSFS_PLATFORM_MACOSX
|
|
||||||
/*
|
|
||||||
* This function is only for OSX. The problem is that Apple's applications
|
|
||||||
* can actually be directory structures with the actual executable nested
|
|
||||||
* several levels down. PhysFS computes the base directory from the Unix
|
|
||||||
* executable, but this may not be the correct directory. Apple tries to
|
|
||||||
* hide everything from the user, so from Finder, the user never sees the
|
|
||||||
* Unix executable, and the directory package (bundle) is considered the
|
|
||||||
* "executable". This means that the correct base directory is at the
|
|
||||||
* level where the directory structure starts.
|
|
||||||
* A typical bundle seems to look like this:
|
|
||||||
* MyApp.app/ <-- top level...this is what the user sees in Finder
|
|
||||||
* Contents/
|
|
||||||
* MacOS/
|
|
||||||
* MyApp <-- the actual executable
|
|
||||||
*
|
|
||||||
* Since anything below the app folder is considered hidden, most
|
|
||||||
* application files need to be at the top level if you intend to
|
|
||||||
* write portable software. Thus if the application resides in:
|
|
||||||
* /Applications/MyProgram
|
|
||||||
* and the executable is the bundle MyApp.app,
|
|
||||||
* PhysFS computes the following as the base directory:
|
|
||||||
* /Applications/MyProgram/MyApp.app/Contents/MacOS/
|
|
||||||
* We need to strip off the MyApp.app/Contents/MacOS/
|
|
||||||
*
|
|
||||||
* However, there are corner cases. OSX applications can be traditional
|
|
||||||
* Unix executables without the bundle. Also, it is not entirely clear
|
|
||||||
* to me what kinds of permutations bundle structures can have.
|
|
||||||
*
|
|
||||||
* For now, this is a temporary hack until a better solution
|
|
||||||
* can be made. This function will try to find a "/Contents/MacOS"
|
|
||||||
* inside the path. If it succeeds, then the path will be truncated
|
|
||||||
* to correct the directory. If it is not found, the path will be
|
|
||||||
* left alone and will presume it is a traditional Unix execuatable.
|
|
||||||
* Most programs also include the .app extention in the top level
|
|
||||||
* folder, but it doesn't seem to be a requirement (Acrobat doesn't
|
|
||||||
* have it). MacOS looks like it can also be MacOSClassic.
|
|
||||||
* This function will test for MacOS and hope it captures any
|
|
||||||
* other permutations.
|
|
||||||
*/
|
|
||||||
static void stripAppleBundle(char *path)
|
|
||||||
{
|
|
||||||
char *sub_str = "/contents/macos";
|
|
||||||
char *found_ptr = NULL;
|
|
||||||
char *tempbuf = NULL;
|
|
||||||
size_t len = strlen(path) + 1;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* !!! FIXME: Can we stack-allocate this? --ryan. */
|
|
||||||
tempbuf = (char *) allocator.Malloc(len);
|
|
||||||
if (!tempbuf) return;
|
|
||||||
memset(tempbuf, '\0', len);
|
|
||||||
|
|
||||||
/* Unlike other Unix filesystems, HFS is case insensitive
|
|
||||||
* It wouldn be nice to use strcasestr, but it doesn't seem
|
|
||||||
* to be available in the OSX gcc library right now.
|
|
||||||
* So we should make a lower case copy of the path to
|
|
||||||
* compare against
|
|
||||||
*/
|
|
||||||
for(i=0; i<strlen(path); i++)
|
|
||||||
{
|
|
||||||
/* convert to lower case */
|
|
||||||
tempbuf[i] = tolower(path[i]);
|
|
||||||
}
|
|
||||||
/* See if we can find "/contents/macos" in the path */
|
|
||||||
found_ptr = strstr(tempbuf, sub_str);
|
|
||||||
if(NULL == found_ptr)
|
|
||||||
{
|
|
||||||
/* It doesn't look like a bundle so we can keep the
|
|
||||||
* original path. Just return */
|
|
||||||
allocator.Free(tempbuf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* We have a bundle, so let's backstep character by character
|
|
||||||
* to erase the extra parts of the path. Quit when we hit
|
|
||||||
* the preceding '/' character.
|
|
||||||
*/
|
|
||||||
for(i=strlen(path)-strlen(found_ptr)-1; i>=0; i--)
|
|
||||||
{
|
|
||||||
if('/' == path[i])
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Safety check */
|
|
||||||
if(i<1)
|
|
||||||
{
|
|
||||||
/* This probably shouldn't happen. */
|
|
||||||
path[0] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Back up one more to remove trailing '/' and set the '\0' */
|
|
||||||
path[i] = '\0';
|
|
||||||
}
|
|
||||||
allocator.Free(tempbuf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformRealPath(const char *path)
|
char *__PHYSFS_platformRealPath(const char *path)
|
||||||
{
|
{
|
||||||
char resolved_path[MAXPATHLEN];
|
char resolved_path[MAXPATHLEN];
|
||||||
|
@ -462,15 +238,51 @@ char *__PHYSFS_platformRealPath(const char *path)
|
||||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||||
strcpy(retval, resolved_path);
|
strcpy(retval, resolved_path);
|
||||||
|
|
||||||
/* !!! FIXME: this shouldn't be here. */
|
|
||||||
#ifdef PHYSFS_PLATFORM_MACOSX
|
|
||||||
stripAppleBundle(retval);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* __PHYSFS_platformRealPath */
|
} /* __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)
|
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a)
|
||||||
{
|
{
|
||||||
return(0); /* just use malloc() and friends. */
|
return(0); /* just use malloc() and friends. */
|
||||||
|
|
Loading…
Reference in New Issue