From ff80fc800344bff127fcb246075b0c93aceccc1f Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 8 Jul 2009 17:46:48 -0400 Subject: [PATCH] Fixed wrong readlink() usage (lstat() doesn't report dest link size!). Thanks to Henk Boom for pointing this out. --- src/platform_unix.c | 52 ++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/src/platform_unix.c b/src/platform_unix.c index 9c33da59..b5759822 100644 --- a/src/platform_unix.c +++ b/src/platform_unix.c @@ -198,12 +198,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) ) @@ -214,20 +244,12 @@ 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) /* chop off filename. */ { - 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 */ + char *ptr = strrchr(retval, '/'); + if (ptr != NULL) + *ptr = '\0'; } /* if */ if ((retval == NULL) && (argv0 != NULL))