platform/unix.c
changeset 520 a72bbf255074
parent 505 c7f7f234a156
child 570 b331437b9ec0
equal deleted inserted replaced
519:c16b1af0919f 520:a72bbf255074
   264 {
   264 {
   265     usleep( 10 * 1000 );           /* don't care if it fails. */
   265     usleep( 10 * 1000 );           /* don't care if it fails. */
   266 } /* __PHYSFS_platformTimeslice */
   266 } /* __PHYSFS_platformTimeslice */
   267 
   267 
   268 
   268 
       
   269 #if defined(__MACH__) && defined(__APPLE__)
       
   270 /* 
       
   271  * This function is only for OSX. The problem is that Apple's applications
       
   272  * can actually be directory structures with the actual executable nested
       
   273  * several levels down. PhysFS computes the base directory from the Unix
       
   274  * executable, but this may not be the correct directory. Apple tries to
       
   275  * hide everything from the user, so from Finder, the user never sees the
       
   276  * Unix executable, and the directory package (bundle) is considered the
       
   277  * "executable". This means that the correct base directory is at the 
       
   278  * level where the directory structure starts.
       
   279  * A typical bundle seems to look like this:
       
   280  * MyApp.app/    <-- top level...this is what the user sees in Finder 
       
   281  *   Contents/
       
   282  *     MacOS/
       
   283  *       MyApp   <-- the actual executable
       
   284  *       
       
   285  * Since anything below the app folder is considered hidden, most 
       
   286  * application files need to be at the top level if you intend to
       
   287  * write portable software. Thus if the application resides in:
       
   288  * /Applications/MyProgram
       
   289  * and the executable is the bundle MyApp.app,
       
   290  * PhysFS computes the following as the base directory:
       
   291  * /Applications/MyProgram/MyApp.app/Contents/MacOS/
       
   292  * We need to strip off the MyApp.app/Contents/MacOS/
       
   293  * 
       
   294  * However, there are corner cases. OSX applications can be traditional
       
   295  * Unix executables without the bundle. Also, it is not entirely clear
       
   296  * to me what kinds of permutations bundle structures can have.
       
   297  * 
       
   298  * For now, this is a temporary hack until a better solution 
       
   299  * can be made. This function will try to find a "/Contents/MacOS"
       
   300  * inside the path. If it succeeds, then the path will be truncated
       
   301  * to correct the directory. If it is not found, the path will be 
       
   302  * left alone and will presume it is a traditional Unix execuatable.
       
   303  * Most programs also include the .app extention in the top level
       
   304  * folder, but it doesn't seem to be a requirement (Acrobat doesn't 
       
   305  * have it). MacOS looks like it can also be MacOSClassic. 
       
   306  * This function will test for MacOS and hope it captures any
       
   307  * other permutations.
       
   308  */
       
   309 static void stripAppleBundle(char *path)
       
   310 {
       
   311     char *sub_str = "/contents/macos";
       
   312     char *found_ptr = NULL;
       
   313     char *tempbuf = NULL;
       
   314     int i;
       
   315     
       
   316     /* Calloc will place the \0 character in the proper place for us */
       
   317     tempbuf = (char*)calloc( (strlen(path)+1), sizeof(char) );
       
   318     /* Unlike other Unix filesystems, HFS is case insensitive
       
   319      * It wouldn be nice to use strcasestr, but it doesn't seem
       
   320      * to be available in the OSX gcc library right now.
       
   321      * So we should make a lower case copy of the path to 
       
   322      * compare against 
       
   323      */
       
   324     for(i=0; i<strlen(path); i++)
       
   325     {
       
   326         /* convert to lower case */
       
   327         tempbuf[i] = tolower(path[i]);
       
   328     }
       
   329     /* See if we can find "/contents/macos" in the path */
       
   330     found_ptr = strstr(tempbuf, sub_str);
       
   331     if(NULL == found_ptr)
       
   332     {
       
   333         /* It doesn't look like a bundle so we can keep the 
       
   334          * original path. Just return */
       
   335         free(tempbuf);
       
   336         return;
       
   337     }
       
   338     /* We have a bundle, so let's backstep character by character
       
   339      * to erase the extra parts of the path. Quit when we hit
       
   340      * the preceding '/' character.
       
   341      */
       
   342     for(i=strlen(path)-strlen(found_ptr)-1; i>=0; i--)
       
   343     {
       
   344         if('/' == path[i])
       
   345         {
       
   346             break;
       
   347         }
       
   348     }
       
   349     /* Safety check */
       
   350     if(i<1)
       
   351     {
       
   352         /* This probably shouldn't happen. */
       
   353         path[0] = '\0';
       
   354     }
       
   355     else
       
   356     {
       
   357         /* Back up one more to remove trailing '/' and set the '\0' */
       
   358         path[i] = '\0';
       
   359     }
       
   360     free(tempbuf);
       
   361     return;
       
   362 }
       
   363 #endif /* defined __MACH__ && defined __APPLE__ */
       
   364 
       
   365 
   269 char *__PHYSFS_platformRealPath(const char *path)
   366 char *__PHYSFS_platformRealPath(const char *path)
   270 {
   367 {
   271     char resolved_path[MAXPATHLEN];
   368     char resolved_path[MAXPATHLEN];
   272     char *retval = NULL;
   369     char *retval = NULL;
   273 
   370 
   274     errno = 0;
   371     errno = 0;
   275     BAIL_IF_MACRO(!realpath(path, resolved_path), strerror(errno), NULL);
   372     BAIL_IF_MACRO(!realpath(path, resolved_path), strerror(errno), NULL);
   276     retval = (char *) malloc(strlen(resolved_path) + 1);
   373     retval = (char *) malloc(strlen(resolved_path) + 1);
   277     BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
   374     BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
   278     strcpy(retval, resolved_path);
   375     strcpy(retval, resolved_path);
       
   376 
       
   377 #if defined(__MACH__) && defined(__APPLE__)
       
   378     stripAppleBundle(retval);
       
   379 #endif /* defined __MACH__ && defined __APPLE__ */
       
   380     
   279     return(retval);
   381     return(retval);
   280 } /* __PHYSFS_platformRealPath */
   382 } /* __PHYSFS_platformRealPath */
   281 
   383 
   282 
   384 
   283 #if (defined PHYSFS_NO_PTHREADS_SUPPORT)
   385 #if (defined PHYSFS_NO_PTHREADS_SUPPORT)