From 16ee8355db5f2fefd3abb02145dc4ee418483c66 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 29 Nov 2012 11:47:16 -0500 Subject: [PATCH] Centralize responsibility for filtering symlinks during enumeration. --- src/archiver_dir.c | 6 ++--- src/archiver_grp.c | 1 + src/archiver_hog.c | 1 + src/archiver_iso9660.c | 2 +- src/archiver_lzma.c | 3 ++- src/archiver_mvl.c | 1 + src/archiver_qpak.c | 1 + src/archiver_slb.c | 1 + src/archiver_unpacked.c | 2 +- src/archiver_wad.c | 1 + src/archiver_zip.c | 6 ++--- src/physfs.c | 59 ++++++++++++++++++++++++++++++++++++++--- src/physfs.h | 5 +--- src/physfs_internal.h | 3 +-- src/platform_posix.c | 46 +------------------------------- src/platform_windows.c | 3 --- 16 files changed, 73 insertions(+), 68 deletions(-) diff --git a/src/archiver_dir.c b/src/archiver_dir.c index c19bb7f5..056c3c26 100644 --- a/src/archiver_dir.c +++ b/src/archiver_dir.c @@ -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 ", "http://icculus.org/physfs/", }, + 1, /* supportsSymlinks */ DIR_openArchive, /* openArchive() method */ DIR_enumerateFiles, /* enumerateFiles() method */ DIR_openRead, /* openRead() method */ diff --git a/src/archiver_grp.c b/src/archiver_grp.c index bdfc65b1..ec6552f9 100644 --- a/src/archiver_grp.c +++ b/src/archiver_grp.c @@ -94,6 +94,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_GRP = "Ryan C. Gordon ", "http://icculus.org/physfs/", }, + 0, /* supportsSymlinks */ GRP_openArchive, /* openArchive() method */ UNPK_enumerateFiles, /* enumerateFiles() method */ UNPK_openRead, /* openRead() method */ diff --git a/src/archiver_hog.c b/src/archiver_hog.c index db195085..b5b88578 100644 --- a/src/archiver_hog.c +++ b/src/archiver_hog.c @@ -100,6 +100,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_HOG = "Bradley Bell ", "http://icculus.org/physfs/", }, + 0, /* supportsSymlinks */ HOG_openArchive, /* openArchive() method */ UNPK_enumerateFiles, /* enumerateFiles() method */ UNPK_openRead, /* openRead() method */ diff --git a/src/archiver_iso9660.c b/src/archiver_iso9660.c index 798f10fd..f6719313 100644 --- a/src/archiver_iso9660.c +++ b/src/archiver_iso9660.c @@ -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 ", "http://www.evilazrael.de/", }, + 0, /* supportsSymlinks */ ISO9660_openArchive, /* openArchive() method */ ISO9660_enumerateFiles, /* enumerateFiles() method */ ISO9660_openRead, /* openRead() method */ diff --git a/src/archiver_lzma.c b/src/archiver_lzma.c index 77072589..266720c2 100644 --- a/src/archiver_lzma.c +++ b/src/archiver_lzma.c @@ -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 ", "http://icculus.org/physfs/", }, + 0, /* supportsSymlinks */ LZMA_openArchive, /* openArchive() method */ LZMA_enumerateFiles, /* enumerateFiles() method */ LZMA_openRead, /* openRead() method */ diff --git a/src/archiver_mvl.c b/src/archiver_mvl.c index 0843e5d7..42d5e091 100644 --- a/src/archiver_mvl.c +++ b/src/archiver_mvl.c @@ -87,6 +87,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_MVL = "Bradley Bell ", "http://icculus.org/physfs/", }, + 0, /* supportsSymlinks */ MVL_openArchive, /* openArchive() method */ UNPK_enumerateFiles, /* enumerateFiles() method */ UNPK_openRead, /* openRead() method */ diff --git a/src/archiver_qpak.c b/src/archiver_qpak.c index af0323dd..c2edfe06 100644 --- a/src/archiver_qpak.c +++ b/src/archiver_qpak.c @@ -103,6 +103,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_QPAK = "Ryan C. Gordon ", "http://icculus.org/physfs/", }, + 0, /* supportsSymlinks */ QPAK_openArchive, /* openArchive() method */ UNPK_enumerateFiles, /* enumerateFiles() method */ UNPK_openRead, /* openRead() method */ diff --git a/src/archiver_slb.c b/src/archiver_slb.c index ece8ae7f..00e05e6d 100644 --- a/src/archiver_slb.c +++ b/src/archiver_slb.c @@ -108,6 +108,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_SLB = "Aleksi Nurmi ", "http://bitbucket.org/ahnurmi/", }, + 0, /* supportsSymlinks */ SLB_openArchive, /* openArchive() method */ UNPK_enumerateFiles, /* enumerateFiles() method */ UNPK_openRead, /* openRead() method */ diff --git a/src/archiver_unpacked.c b/src/archiver_unpacked.c index d751351f..3adf35bb 100644 --- a/src/archiver_unpacked.c +++ b/src/archiver_unpacked.c @@ -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); diff --git a/src/archiver_wad.c b/src/archiver_wad.c index 535c00b9..ac8230f4 100644 --- a/src/archiver_wad.c +++ b/src/archiver_wad.c @@ -111,6 +111,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_WAD = "Travis Wells ", "http://www.3dmm2.com/doom/", }, + 0, /* supportsSymlinks */ WAD_openArchive, /* openArchive() method */ UNPK_enumerateFiles, /* enumerateFiles() method */ UNPK_openRead, /* openRead() method */ diff --git a/src/archiver_zip.c b/src/archiver_zip.c index 848aa77c..e0dd371d 100644 --- a/src/archiver_zip.c +++ b/src/archiver_zip.c @@ -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 ", "http://icculus.org/physfs/", }, + 1, /* supportsSymlinks */ ZIP_openArchive, /* openArchive() method */ ZIP_enumerateFiles, /* enumerateFiles() method */ ZIP_openRead, /* openRead() method */ diff --git a/src/physfs.c b/src/physfs.c index e1b92ba6..3de96dce 100644 --- a/src/physfs.c +++ b/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); diff --git a/src/physfs.h b/src/physfs.h index 69c399ba..58f9b99a 100644 --- a/src/physfs.h +++ b/src/physfs.h @@ -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); /** diff --git a/src/physfs_internal.h b/src/physfs_internal.h index 9a8dee14..d16f02f5 100644 --- a/src/physfs_internal.h +++ b/src/physfs_internal.h @@ -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); diff --git a/src/platform_posix.c b/src/platform_posix.c index 0822be2b..f446a376 100644 --- a/src/platform_posix.c +++ b/src/platform_posix.c @@ -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 */ diff --git a/src/platform_windows.c b/src/platform_windows.c index 7b38a98c..44ce02d8 100644 --- a/src/platform_windows.c +++ b/src/platform_windows.c @@ -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)