Added hack for OSX bundles, from Eric Wing.
This commit is contained in:
parent
7b5f74c502
commit
8701e4d98d
102
platform/unix.c
102
platform/unix.c
|
@ -266,6 +266,103 @@ void __PHYSFS_platformTimeslice(void)
|
||||||
} /* __PHYSFS_platformTimeslice */
|
} /* __PHYSFS_platformTimeslice */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Calloc will place the \0 character in the proper place for us */
|
||||||
|
tempbuf = (char*)calloc( (strlen(path)+1), sizeof(char) );
|
||||||
|
/* 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 */
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
free(tempbuf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* defined __MACH__ && defined __APPLE__ */
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformRealPath(const char *path)
|
char *__PHYSFS_platformRealPath(const char *path)
|
||||||
{
|
{
|
||||||
char resolved_path[MAXPATHLEN];
|
char resolved_path[MAXPATHLEN];
|
||||||
|
@ -276,6 +373,11 @@ char *__PHYSFS_platformRealPath(const char *path)
|
||||||
retval = (char *) malloc(strlen(resolved_path) + 1);
|
retval = (char *) malloc(strlen(resolved_path) + 1);
|
||||||
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);
|
||||||
|
|
||||||
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
|
stripAppleBundle(retval);
|
||||||
|
#endif /* defined __MACH__ && defined __APPLE__ */
|
||||||
|
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* __PHYSFS_platformRealPath */
|
} /* __PHYSFS_platformRealPath */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue