Skip to content

Commit

Permalink
Whoops, apparently stat::st_size isn't set to the string length of a …
Browse files Browse the repository at this point in the history
…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).
  • Loading branch information
icculus committed Jul 2, 2007
1 parent d8bf02c commit 504d310
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 12 deletions.
6 changes: 2 additions & 4 deletions fileio.c
Expand Up @@ -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"
Expand Down Expand Up @@ -415,13 +414,12 @@ static const MojoArchiveEntry *MojoArchive_dir_enumNext(MojoArchive *ar)
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))
Expand Down
5 changes: 5 additions & 0 deletions platform.h
Expand Up @@ -49,6 +49,11 @@ char *MojoPlatform_realpath(const char *path);
// 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);

Expand Down
34 changes: 26 additions & 8 deletions platform_unix.c
Expand Up @@ -82,6 +82,29 @@ char *MojoPlatform_currentWorkingDir(void)
} // 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;
Expand Down Expand Up @@ -176,19 +199,13 @@ static char *realpathInternal(char *path, const char *cwd, int linkloop)
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';

Expand All @@ -202,6 +219,7 @@ static char *realpathInternal(char *path, const char *cwd, int linkloop)
strcpy(retval, newresolve);
free(newresolve);
free(linkname);
linkname = NULL;
} // else if

else
Expand Down

0 comments on commit 504d310

Please sign in to comment.