Skip to content
Permalink
Browse files
Merged 1001:b0c6f2f4f361 through 1003:a28d30d275e2 from default branch.
Fixes /proc/*/exe behaviour on Linux.
  • Loading branch information
icculus committed Jul 8, 2009
1 parent 8978c7d commit d9f0a872080ae9e17a66fecafc2dd6768473e118
Showing with 55 additions and 15 deletions.
  1. +55 −15 platform/unix.c
@@ -182,12 +182,42 @@ static char *findBinaryInPath(const char *bin, char *envr)
} /* findBinaryInPath */


static char *readSymLink(const char *path)
{
ssize_t len = 64;
ssize_t rc = -1;
char *retval = NULL;

while (1)
{
char *ptr = (char *) allocator.Realloc(retval, (size_t) len);
if (ptr == NULL)
break; /* out of memory. */
retval = ptr;

rc = readlink(path, retval, len);
if (rc == -1)
break; /* not a symlink, i/o error, etc. */

else if (rc < len)
{
retval[rc] = '\0'; /* readlink doesn't null-terminate. */
return retval; /* we're good to go. */
} /* else if */

len *= 2; /* grow buffer, try again. */
} /* while */

if (retval != NULL)
allocator.Free(retval);
return NULL;
} /* readSymLink */


char *__PHYSFS_platformCalcBaseDir(const char *argv0)
{
const char *PROC_SELF_EXE = "/proc/self/exe";
char *retval = NULL;
char *envr = NULL;
struct stat stbuf;

/* fast path: default behaviour can handle this. */
if ( (argv0 != NULL) && (strchr(argv0, '/') != NULL) )
@@ -198,20 +228,22 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
* /proc filesystem, you can get the full path to the current process from
* the /proc/self/exe symlink.
*/
if ((lstat(PROC_SELF_EXE, &stbuf) != -1) && (S_ISLNK(stbuf.st_mode)))
retval = readSymLink("/proc/self/exe");
if (retval == NULL)
{
const size_t len = stbuf.st_size;
char *buf = (char *) allocator.Malloc(len+1);
if (buf != NULL) /* if NULL, maybe you'll get lucky later. */
{
if (readlink(PROC_SELF_EXE, buf, len) != len)
allocator.Free(buf);
else
{
buf[len] = '\0'; /* readlink doesn't null-terminate. */
retval = buf; /* we're good to go. */
} /* else */
} /* if */
/* older kernels don't have /proc/self ... try PID version... */
const unsigned long long pid = (unsigned long long) getpid();
char path[64];
const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid);
if ( (rc > 0) && (rc < sizeof(path)) )
retval = readSymLink(path);
} /* if */

if (retval != NULL) /* chop off filename. */
{
char *ptr = strrchr(retval, '/');
if (ptr != NULL)
*ptr = '\0';
} /* if */

if ((retval == NULL) && (argv0 != NULL))
@@ -223,6 +255,14 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
allocator.Free(envr);
} /* if */

if (retval != NULL)
{
/* try to shrink buffer... */
char *ptr = (char *) allocator.Realloc(retval, strlen(retval) + 1);
if (ptr != NULL)
retval = ptr; /* oh well if it failed. */
} /* if */

return(retval);
} /* __PHYSFS_platformCalcBaseDir */

0 comments on commit d9f0a87

Please sign in to comment.