src/platform_unix.c
changeset 1337 3b2e649c044c
parent 1333 baecd71ae0e7
child 1354 3e80839670da
equal deleted inserted replaced
1335:1b9a72908ece 1337:3b2e649c044c
    11 
    11 
    12 #ifdef PHYSFS_PLATFORM_UNIX
    12 #ifdef PHYSFS_PLATFORM_UNIX
    13 
    13 
    14 #include <ctype.h>
    14 #include <ctype.h>
    15 #include <unistd.h>
    15 #include <unistd.h>
       
    16 #include <stdlib.h>
    16 #include <sys/types.h>
    17 #include <sys/types.h>
    17 #include <pwd.h>
    18 #include <pwd.h>
    18 #include <sys/stat.h>
    19 #include <sys/stat.h>
    19 #include <sys/param.h>
    20 #include <sys/param.h>
    20 #include <dirent.h>
    21 #include <dirent.h>
    21 #include <time.h>
    22 #include <time.h>
    22 #include <errno.h>
    23 #include <errno.h>
       
    24 #include <limits.h>
    23 
    25 
    24 #if PHYSFS_PLATFORM_LINUX && !defined(PHYSFS_HAVE_MNTENT_H)
    26 #if PHYSFS_PLATFORM_LINUX && !defined(PHYSFS_HAVE_MNTENT_H)
    25 #define PHYSFS_HAVE_MNTENT_H 1
    27 #define PHYSFS_HAVE_MNTENT_H 1
    26 #elif PHYSFS_PLATFORM_SOLARIS && !defined(PHYSFS_HAVE_SYS_MNTTAB_H)
    28 #elif PHYSFS_PLATFORM_SOLARIS && !defined(PHYSFS_HAVE_SYS_MNTTAB_H)
    27 #define PHYSFS_HAVE_SYS_MNTTAB_H 1
    29 #define PHYSFS_HAVE_SYS_MNTTAB_H 1
   242 char *__PHYSFS_platformCalcBaseDir(const char *argv0)
   244 char *__PHYSFS_platformCalcBaseDir(const char *argv0)
   243 {
   245 {
   244     char *retval = NULL;
   246     char *retval = NULL;
   245     const char *envr = NULL;
   247     const char *envr = NULL;
   246 
   248 
   247     /*
   249     /* Try to avoid using argv0 unless forced to. Try system-specific stuff. */
   248      * Try to avoid using argv0 unless forced to. If there's a Linux-like
   250     
   249      *  /proc filesystem, you can get the full path to the current process from
   251     #if PHYSFS_PLATFORM_FREEBSD
   250      *  the /proc/self/exe symlink.
   252     {
       
   253         char fullpath[PATH_MAX];
       
   254         size_t buflen = sizeof (fullpath);
       
   255         int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
       
   256         if (sysctl(mib, 4, fullpath, &buflen, NULL, 0) != -1)
       
   257             retval = __PHYSFS_strdup(fullpath);
       
   258     }
       
   259     #elif PHYSFS_PLATFORM_SOLARIS
       
   260     {
       
   261         const char *path = getexecname();
       
   262         if ((path != NULL) && (path[0] == '/'))  /* must be absolute path... */
       
   263             retval = __PHYSFS_strdup(path);
       
   264     }
       
   265     #endif
       
   266 
       
   267     if (retval)
       
   268         return retval;   /* already got it. */
       
   269 
       
   270     /* If there's a Linux-like /proc filesystem, you can get the full path to
       
   271      *  the current process from a symlink in there.
   251      */
   272      */
   252     retval = readSymLink("/proc/self/exe");
   273 
   253     if (retval == NULL)
   274     if (access("/proc", F_OK) == 0)
   254     {
   275     {
   255         /* older kernels don't have /proc/self ... try PID version... */
   276         retval = readSymLink("/proc/self/exe");
   256         const unsigned long long pid = (unsigned long long) getpid();
   277         if (!retval) retval = readSymLink("/proc/curproc/file");
   257         char path[64];
   278         if (!retval) retval = readSymLink("/proc/curproc/exe");
   258         const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid);
   279         if (retval == NULL)
   259         if ( (rc > 0) && (rc < sizeof(path)) )
   280         {
   260             retval = readSymLink(path);
   281             /* older kernels don't have /proc/self ... try PID version... */
       
   282             const unsigned long long pid = (unsigned long long) getpid();
       
   283             char path[64];
       
   284             const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid);
       
   285             if ( (rc > 0) && (rc < sizeof(path)) )
       
   286                 retval = readSymLink(path);
       
   287         } /* if */
   261     } /* if */
   288     } /* if */
   262 
   289 
   263     if (retval != NULL)  /* chop off filename. */
   290     if (retval != NULL)  /* chop off filename. */
   264     {
   291     {
   265         char *ptr = strrchr(retval, '/');
   292         char *ptr = strrchr(retval, '/');
   270             allocator.Free(retval);
   297             allocator.Free(retval);
   271             retval = NULL;
   298             retval = NULL;
   272         } /* else */
   299         } /* else */
   273     } /* if */
   300     } /* if */
   274 
   301 
   275     /* No /proc/self/exe, but we have an argv[0] we can parse? */
   302     /* No /proc/self/exe, etc, but we have an argv[0] we can parse? */
   276     if ((retval == NULL) && (argv0 != NULL))
   303     if ((retval == NULL) && (argv0 != NULL))
   277     {
   304     {
   278         /* fast path: default behaviour can handle this. */
   305         /* fast path: default behaviour can handle this. */
   279         if (strchr(argv0, '/') != NULL)
   306         if (strchr(argv0, '/') != NULL)
   280             return NULL;  /* higher level parses out real path from argv0. */
   307             return NULL;  /* higher level parses out real path from argv0. */