From 075e6769e2718eea5f15cb74b6b8cac11be509c3 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 21 Mar 2007 05:03:17 +0000 Subject: [PATCH] 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. --- CMakeLists.txt | 1 + physfs_platforms.h | 1 - platform/beos.cpp | 11 +- platform/macosx.c | 396 +++++++++++++++++++++++++++++++++++++++++++++ platform/posix.c | 40 +---- platform/unix.c | 270 +++++-------------------------- 6 files changed, 448 insertions(+), 271 deletions(-) create mode 100644 platform/macosx.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fabffce..a7f00d95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,7 @@ SET(PHYSFS_SRCS platform/pocketpc.c platform/posix.c platform/unix.c + platform/macosx.c platform/windows.c archivers/dir.c archivers/grp.c diff --git a/physfs_platforms.h b/physfs_platforms.h index 467a96ca..9f95a890 100644 --- a/physfs_platforms.h +++ b/physfs_platforms.h @@ -23,7 +23,6 @@ # define PHYSFS_PLATFORM_OS2 #elif ((defined __MACH__) && (defined __APPLE__)) # define PHYSFS_PLATFORM_MACOSX -# define PHYSFS_PLATFORM_UNIX # define PHYSFS_PLATFORM_POSIX #elif defined(macintosh) # error Classic Mac OS support was dropped from PhysicsFS 2.0. Move to OS X. diff --git a/platform/beos.cpp b/platform/beos.cpp index cd1cc8e4..06fcc962 100644 --- a/platform/beos.cpp +++ b/platform/beos.cpp @@ -30,9 +30,6 @@ #include "physfs_internal.h" -const char *__PHYSFS_platformDirSeparator = "/"; - - int __PHYSFS_platformInit(void) { return(1); /* always succeed. */ @@ -158,7 +155,7 @@ static team_id getTeamID(void) thread_id tid = find_thread(NULL); get_thread_info(tid, &info); return(info.team); -} /* getMyTeamID */ +} /* getTeamID */ char *__PHYSFS_platformCalcBaseDir(const char *argv0) @@ -201,6 +198,12 @@ char *__PHYSFS_platformRealPath(const char *path) } /* __PHYSFS_platformRealPath */ +char *__PHYSFS_platformCurrentDir(void) +{ + return(__PHYSFS_platformRealPath(".")); /* let BPath sort it out. */ +} /* __PHYSFS_platformCurrentDir */ + + /* !!! FIXME: semaphores are not mutexes... */ void *__PHYSFS_platformCreateMutex(void) { diff --git a/platform/macosx.c b/platform/macosx.c new file mode 100644 index 00000000..93d6183d --- /dev/null +++ b/platform/macosx.c @@ -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 +#include +#include +#include +#include + +/* 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 ... */ + diff --git a/platform/posix.c b/platform/posix.c index d3d33f88..5464face 100644 --- a/platform/posix.c +++ b/platform/posix.c @@ -30,6 +30,9 @@ #include "physfs_internal.h" +const char *__PHYSFS_platformDirSeparator = "/"; + + char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname) { const char *envr = getenv(varname); @@ -224,43 +227,6 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname, } /* __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 rc; diff --git a/platform/unix.c b/platform/unix.c index 5bf86147..858f3be6 100644 --- a/platform/unix.c +++ b/platform/unix.c @@ -25,15 +25,6 @@ #include #include -#ifdef PHYSFS_PLATFORM_MACOSX -# include -# include -# include -# include -# include -# include -#endif - #if (!defined PHYSFS_NO_PTHREADS_SUPPORT) #include #endif @@ -51,13 +42,6 @@ #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) { @@ -78,113 +62,6 @@ void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data) { } /* __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) void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data) @@ -350,107 +227,6 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0) } /* __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=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 resolved_path[MAXPATHLEN]; @@ -462,15 +238,51 @@ char *__PHYSFS_platformRealPath(const char *path) BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); strcpy(retval, resolved_path); -/* !!! FIXME: this shouldn't be here. */ -#ifdef PHYSFS_PLATFORM_MACOSX - stripAppleBundle(retval); -#endif - 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. */