r331 - trunk

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Jul 2 03:54:47 EDT 2007


Author: icculus
Date: 2007-07-02 03:54:42 -0400 (Mon, 02 Jul 2007)
New Revision: 331

Modified:
   trunk/fileio.c
   trunk/platform.h
   trunk/platform_unix.c
Log:
Whoops, apparently stat::st_size isn't set to the string length of a symlink's
 linkdest, so we were misallocating buffers here for the readlink().

With that in mind, I made an platform layer abstraction for readlink() and
 made the unix one robust to handle when we don't know the linkdest's size
 (er...which is always, but readlink() isn't real helpful here either).


Modified: trunk/fileio.c
===================================================================
--- trunk/fileio.c	2007-07-02 07:28:35 UTC (rev 330)
+++ trunk/fileio.c	2007-07-02 07:54:42 UTC (rev 331)
@@ -6,7 +6,6 @@
  *  This file written by Ryan C. Gordon.
  */
 
-#include <unistd.h>  // !!! FIXME: unix dependency for readlink().
 #include <sys/stat.h>  // !!! FIXME: unix dependency for stat().
 
 #include "fileio.h"
@@ -415,13 +414,12 @@
         else if (S_ISLNK(statbuf.st_mode))
         {
             ar->prevEnum.type = MOJOARCHIVE_ENTRY_SYMLINK;
-            ar->prevEnum.linkdest = (char *) xmalloc(statbuf.st_size + 1);
-            if (readlink(fullpath, ar->prevEnum.linkdest, statbuf.st_size) < 0)
+            ar->prevEnum.linkdest = MojoPlatform_readlink(fullpath);
+            if (ar->prevEnum.linkdest == NULL)
             {
                 free(fullpath);
                 return MojoArchive_dir_enumNext(ar);
             } // if
-            ar->prevEnum.linkdest[statbuf.st_size] = '\0';
         } // else if
 
         else if (S_ISDIR(statbuf.st_mode))

Modified: trunk/platform.h
===================================================================
--- trunk/platform.h	2007-07-02 07:28:35 UTC (rev 330)
+++ trunk/platform.h	2007-07-02 07:54:42 UTC (rev 331)
@@ -49,6 +49,11 @@
 //  syscall! Returns true if link was created, false otherwise.
 boolean MojoPlatform_symlink(const char *src, const char *dst);
 
+// Read the destination from symlink (linkname). Returns a pointer
+//  allocated with xmalloc() containing the linkdest on success, and NULL
+//  on failure. The caller is responsible for freeing the returned pointer!
+char *MojoPlatform_readlink(const char *linkname);
+
 // !!! FIXME: comment me.
 boolean MojoPlatform_mkdir(const char *path, uint16 perms);
 

Modified: trunk/platform_unix.c
===================================================================
--- trunk/platform_unix.c	2007-07-02 07:28:35 UTC (rev 330)
+++ trunk/platform_unix.c	2007-07-02 07:54:42 UTC (rev 331)
@@ -82,6 +82,29 @@
 } // MojoPlatform_currentWorkingDir
 
 
+char *MojoPlatform_readlink(const char *linkname)
+{
+    size_t alloclen = 16;
+    char *retval = NULL;
+    char *buf = NULL;
+    size_t len = -1;
+
+    do
+    {
+        alloclen *= 2;
+        buf = xrealloc(buf, alloclen);
+        len = readlink(linkname, buf, alloclen-1);
+        if ( (len != -1) && (len < (alloclen-1)) )  // !error && !overflow
+        {
+            buf[len] = '\0';  // readlink() doesn't null-terminate!
+            retval = xrealloc(buf, len+1);  // shrink it down.
+        } // if
+    } while (len >= (alloclen-1));  // loop if we need a bigger buffer.
+
+    return retval;  // caller must free() this.
+} // MojoPlatform_readlink
+
+
 static void *guaranteeAllocation(void *ptr, size_t len, size_t *_alloclen)
 {
     void *retval = NULL;
@@ -176,19 +199,13 @@
         else if (S_ISLNK(statbuf.st_mode))
         {
             char *newresolve = NULL;
-            int br = 0;
-
             if (linkloop > 255)
                 goto realpathInternal_failed;
 
-            linkname = (char *) xmalloc(statbuf.st_size + 1);
-            br = readlink(retval, linkname, statbuf.st_size);
-            if (br < 0)
+            linkname = MojoPlatform_readlink(retval);
+            if (linkname == NULL)
                 goto realpathInternal_failed;
 
-            // readlink() doesn't null-terminate!
-            linkname[br] = '\0';
-
             // chop off symlink name for its cwd.
             retval[len] = '\0';
 
@@ -202,6 +219,7 @@
             strcpy(retval, newresolve);
             free(newresolve);
             free(linkname);
+            linkname = NULL;
         } // else if
 
         else




More information about the mojosetup-commits mailing list