Skip to content
Permalink
Browse files
Centralize responsibility for filtering symlinks during enumeration.
  • Loading branch information
icculus committed Nov 29, 2012
1 parent 2593991 commit 16ee8355db5f2fefd3abb02145dc4ee418483c66
@@ -67,16 +67,15 @@ static void *DIR_openArchive(PHYSFS_Io *io, const char *name, int forWriting)


static void DIR_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
char *d;

CVT_TO_DEPENDENT(d, opaque, dname);
if (d != NULL)
{
__PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
origdir, callbackdata);
__PHYSFS_platformEnumerateFiles(d, cb, origdir, callbackdata);
__PHYSFS_smallFree(d);
} /* if */
} /* DIR_enumerateFiles */
@@ -187,6 +186,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
"Ryan C. Gordon <icculus@icculus.org>",
"http://icculus.org/physfs/",
},
1, /* supportsSymlinks */
DIR_openArchive, /* openArchive() method */
DIR_enumerateFiles, /* enumerateFiles() method */
DIR_openRead, /* openRead() method */
@@ -94,6 +94,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
"Ryan C. Gordon <icculus@icculus.org>",
"http://icculus.org/physfs/",
},
0, /* supportsSymlinks */
GRP_openArchive, /* openArchive() method */
UNPK_enumerateFiles, /* enumerateFiles() method */
UNPK_openRead, /* openRead() method */
@@ -100,6 +100,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
"Bradley Bell <btb@icculus.org>",
"http://icculus.org/physfs/",
},
0, /* supportsSymlinks */
HOG_openArchive, /* openArchive() method */
UNPK_enumerateFiles, /* enumerateFiles() method */
UNPK_openRead, /* openRead() method */
@@ -817,7 +817,6 @@ static PHYSFS_Io *ISO9660_openRead(void *opaque, const char *filename,
******************************************************************************/

static void ISO9660_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks,
PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
@@ -953,6 +952,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660 =
"Christoph Nelles <evilazrael@evilazrael.de>",
"http://www.evilazrael.de/",
},
0, /* supportsSymlinks */
ISO9660_openArchive, /* openArchive() method */
ISO9660_enumerateFiles, /* enumerateFiles() method */
ISO9660_openRead, /* openRead() method */
@@ -532,7 +532,7 @@ static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,


static void LZMA_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
size_t dlen = strlen(dname),
@@ -685,6 +685,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
"Dennis Schridde <devurandom@gmx.net>",
"http://icculus.org/physfs/",
},
0, /* supportsSymlinks */
LZMA_openArchive, /* openArchive() method */
LZMA_enumerateFiles, /* enumerateFiles() method */
LZMA_openRead, /* openRead() method */
@@ -87,6 +87,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
"Bradley Bell <btb@icculus.org>",
"http://icculus.org/physfs/",
},
0, /* supportsSymlinks */
MVL_openArchive, /* openArchive() method */
UNPK_enumerateFiles, /* enumerateFiles() method */
UNPK_openRead, /* openRead() method */
@@ -103,6 +103,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
"Ryan C. Gordon <icculus@icculus.org>",
"http://icculus.org/physfs/",
},
0, /* supportsSymlinks */
QPAK_openArchive, /* openArchive() method */
UNPK_enumerateFiles, /* enumerateFiles() method */
UNPK_openRead, /* openRead() method */
@@ -108,6 +108,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_SLB =
"Aleksi Nurmi <aleksi.nurmi@gmail.com>",
"http://bitbucket.org/ahnurmi/",
},
0, /* supportsSymlinks */
SLB_openArchive, /* openArchive() method */
UNPK_enumerateFiles, /* enumerateFiles() method */
UNPK_openRead, /* openRead() method */
@@ -243,7 +243,7 @@ static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,


void UNPK_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
UNPKinfo *info = ((UNPKinfo *) opaque);
@@ -111,6 +111,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
"Travis Wells <traviswells@mchsi.com>",
"http://www.3dmm2.com/doom/",
},
0, /* supportsSymlinks */
WAD_openArchive, /* openArchive() method */
UNPK_enumerateFiles, /* enumerateFiles() method */
UNPK_openRead, /* openRead() method */
@@ -1488,7 +1488,7 @@ static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,


static void ZIP_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
ZIPinfo *info = ((ZIPinfo *) opaque);
@@ -1510,9 +1510,6 @@ static void ZIP_enumerateFiles(void *opaque, const char *dname,
char *e = info->entries[i].name;
if ((dlen) && ((strncmp(e, dname, dlen) != 0) || (e[dlen] != '/')))
break; /* past end of this dir; we're done. */

if ((omitSymLinks) && (zip_entry_is_symlink(&info->entries[i])))
i++;
else
{
char *add = e + dlen_inc;
@@ -1701,6 +1698,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_ZIP =
"Ryan C. Gordon <icculus@icculus.org>",
"http://icculus.org/physfs/",
},
1, /* supportsSymlinks */
ZIP_openArchive, /* openArchive() method */
ZIP_enumerateFiles, /* enumerateFiles() method */
ZIP_openRead, /* openRead() method */
@@ -2245,6 +2245,40 @@ static void enumerateFromMountPoint(DirHandle *i, const char *arcfname,
} /* enumerateFromMountPoint */


typedef struct SymlinkFilterData
{
PHYSFS_EnumFilesCallback callback;
void *callbackData;
DirHandle *dirhandle;
} SymlinkFilterData;

static void enumCallbackFilterSymLinks(void *_data, const char *origdir,
const char *fname)
{
const char *trimmedDir = (*origdir == '/') ? (origdir+1) : origdir;
const size_t slen = strlen(trimmedDir) + strlen(fname) + 2;
char *path = (char *) __PHYSFS_smallAlloc(slen);

if (path != NULL)
{
SymlinkFilterData *data = (SymlinkFilterData *) _data;
const DirHandle *dh = data->dirhandle;
PHYSFS_Stat statbuf;
int exists = 0;

sprintf(path, "%s%s%s", trimmedDir, *trimmedDir ? "/" : "", fname);
if (dh->funcs->stat(dh->opaque, path, &exists, &statbuf))
{
/* Pass it on to the application if it's not a symlink. */
if (statbuf.filetype != PHYSFS_FILETYPE_SYMLINK)
data->callback(data->callbackData, origdir, fname);
} /* if */

__PHYSFS_smallFree(path);
} /* if */
} /* enumCallbackFilterSymLinks */


/* !!! FIXME: this should report error conditions. */
void PHYSFS_enumerateFilesCallback(const char *_fname,
PHYSFS_EnumFilesCallback callback,
@@ -2263,10 +2297,17 @@ void PHYSFS_enumerateFilesCallback(const char *_fname,
if (sanitizePlatformIndependentPath(_fname, fname))
{
DirHandle *i;
int noSyms;
SymlinkFilterData filterdata;

__PHYSFS_platformGrabMutex(stateLock);
noSyms = !allowSymLinks;

if (!allowSymLinks)
{
memset(&filterdata, '\0', sizeof (filterdata));
filterdata.callback = callback;
filterdata.callbackData = data;
} /* if */

for (i = searchPath; i != NULL; i = i->next)
{
char *arcfname = fname;
@@ -2275,8 +2316,18 @@ void PHYSFS_enumerateFilesCallback(const char *_fname,

else if (verifyPath(i, &arcfname, 0))
{
i->funcs->enumerateFiles(i->opaque, arcfname, noSyms,
callback, _fname, data);
if ((!allowSymLinks) && (i->funcs->supportsSymlinks))
{
filterdata.dirhandle = i;
i->funcs->enumerateFiles(i->opaque, arcfname,
enumCallbackFilterSymLinks,
_fname, &filterdata);
} /* if */
else
{
i->funcs->enumerateFiles(i->opaque, arcfname,
callback, _fname, data);
} /* else */
} /* else if */
} /* for */
__PHYSFS_platformReleaseMutex(stateLock);
@@ -3408,14 +3408,11 @@ typedef struct PHYSFS_Archiver
* List all files in (dirname). Each file is passed to (cb),
* where a copy is made if appropriate, so you should dispose of
* it properly upon return from the callback.
* You should omit symlinks if (omitSymLinks) is non-zero.
* If you have a failure, report as much as you can.
* (dirname) is in platform-independent notation.
*/

// !!! FIXME: get rid of this omitsymlinks nonsense.
void (*enumerateFiles)(void *opaque, const char *dirname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata);

/**
@@ -301,7 +301,7 @@ typedef struct
void UNPK_closeArchive(void *opaque);
void *UNPK_openArchive(PHYSFS_Io *io,UNPKentry *e,const PHYSFS_uint32 n);
void UNPK_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata);
PHYSFS_Io *UNPK_openRead(void *opaque, const char *fnm, int *fileExists);
PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name);
@@ -555,7 +555,6 @@ void *__PHYSFS_platformGetThreadID(void);
* metaentries should always be ignored.
*/
void __PHYSFS_platformEnumerateFiles(const char *dirname,
int omitSymLinks,
PHYSFS_EnumFilesCallback callback,
const char *origdir,
void *callbackdata);
@@ -122,31 +122,13 @@ char *__PHYSFS_platformCalcUserDir(void)


void __PHYSFS_platformEnumerateFiles(const char *dirname,
int omitSymLinks,
PHYSFS_EnumFilesCallback callback,
const char *origdir,
void *callbackdata)
{
DIR *dir;
struct dirent *ent;
int bufsize = 0;
char *buf = NULL;
int dlen = 0;

if (omitSymLinks) /* !!! FIXME: this malloc sucks. */
{
dlen = strlen(dirname);
bufsize = dlen + 256;
buf = (char *) allocator.Malloc(bufsize);
if (buf == NULL)
return;
strcpy(buf, dirname);
if (buf[dlen - 1] != '/')
{
buf[dlen++] = '/';
buf[dlen] = '\0';
} /* if */
} /* if */

errno = 0;
dir = opendir(dirname);
@@ -160,35 +142,9 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
{
if (strcmp(ent->d_name, ".") == 0)
continue;

if (strcmp(ent->d_name, "..") == 0)
else if (strcmp(ent->d_name, "..") == 0)
continue;

if (omitSymLinks)
{
PHYSFS_Stat statbuf;
int exists = 0;
char *p;
int len = strlen(ent->d_name) + dlen + 1;
if (len > bufsize)
{
p = (char *) allocator.Realloc(buf, len);
if (p == NULL)
continue;
buf = p;
bufsize = len;
} /* if */

strcpy(buf + dlen, ent->d_name);

if (!__PHYSFS_platformStat(buf, &exists, &statbuf))
continue;
else if (!exists)
continue; /* probably can't happen, but just in case. */
else if (statbuf.filetype == PHYSFS_FILETYPE_SYMLINK)
continue;
} /* if */

callback(callbackdata, origdir, ent->d_name);
} /* while */

@@ -487,7 +487,6 @@ static int isSymlinkAttrs(const DWORD attr, const DWORD tag)


void __PHYSFS_platformEnumerateFiles(const char *dirname,
int omitSymLinks,
PHYSFS_EnumFilesCallback callback,
const char *origdir,
void *callbackdata)
@@ -538,8 +537,6 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
continue;
if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0'))
continue;
if ((omitSymLinks) && (isSymlinkAttrs(attr, tag)))
continue;

utf8 = unicodeToUtf8Heap(fn);
if (utf8 != NULL)

0 comments on commit 16ee835

Please sign in to comment.