Browse Source

Fixed wrong readlink() usage (lstat() doesn't report dest link size!).

Thanks to Henk Boom for pointing this out.
Ryan C. Gordon 17 năm trước cách đây
mục cha
commit
ff80fc8003
1 tập tin đã thay đổi với 37 bổ sung15 xóa
  1. 37 15
      src/platform_unix.c

+ 37 - 15
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))