Centralize responsibility for filtering symlinks during enumeration.
This commit is contained in:
parent
259399124a
commit
16ee8355db
|
@ -67,7 +67,7 @@ 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;
|
||||
|
@ -75,8 +75,7 @@ static void DIR_enumerateFiles(void *opaque, const char *dname,
|
|||
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 @@ errorhandling:
|
|||
******************************************************************************/
|
||||
|
||||
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 */
|
||||
|
|
59
src/physfs.c
59
src/physfs.c
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue