Centralize responsibility for filtering symlinks during enumeration.
authorRyan C. Gordon <icculus@icculus.org>
Thu, 29 Nov 2012 11:47:16 -0500
changeset 1324 d12c1c033a7d
parent 1323 61ca5d6011df
child 1325 4fa1518513c4
Centralize responsibility for filtering symlinks during enumeration.
src/archiver_dir.c
src/archiver_grp.c
src/archiver_hog.c
src/archiver_iso9660.c
src/archiver_lzma.c
src/archiver_mvl.c
src/archiver_qpak.c
src/archiver_slb.c
src/archiver_unpacked.c
src/archiver_wad.c
src/archiver_zip.c
src/physfs.c
src/physfs.h
src/physfs_internal.h
src/platform_posix.c
src/platform_windows.c
--- a/src/archiver_dir.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_dir.c	Thu Nov 29 11:47:16 2012 -0500
@@ -67,7 +67,7 @@
 
 
 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 @@
     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 @@
         "Ryan C. Gordon <icculus@icculus.org>",
         "http://icculus.org/physfs/",
     },
+    1,  /* supportsSymlinks */
     DIR_openArchive,        /* openArchive() method    */
     DIR_enumerateFiles,     /* enumerateFiles() method */
     DIR_openRead,           /* openRead() method       */
--- a/src/archiver_grp.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_grp.c	Thu Nov 29 11:47:16 2012 -0500
@@ -94,6 +94,7 @@
         "Ryan C. Gordon <icculus@icculus.org>",
         "http://icculus.org/physfs/",
     },
+    0,  /* supportsSymlinks */
     GRP_openArchive,        /* openArchive() method    */
     UNPK_enumerateFiles,    /* enumerateFiles() method */
     UNPK_openRead,          /* openRead() method       */
--- a/src/archiver_hog.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_hog.c	Thu Nov 29 11:47:16 2012 -0500
@@ -100,6 +100,7 @@
         "Bradley Bell <btb@icculus.org>",
         "http://icculus.org/physfs/",
     },
+    0,  /* supportsSymlinks */
     HOG_openArchive,         /* openArchive() method    */
     UNPK_enumerateFiles,     /* enumerateFiles() method */
     UNPK_openRead,           /* openRead() method       */
--- a/src/archiver_iso9660.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_iso9660.c	Thu Nov 29 11:47:16 2012 -0500
@@ -817,7 +817,6 @@
  ******************************************************************************/
 
 static void ISO9660_enumerateFiles(void *opaque, const char *dname,
-                                   int omitSymLinks,
                                    PHYSFS_EnumFilesCallback cb,
                                    const char *origdir, void *callbackdata)
 {
@@ -953,6 +952,7 @@
         "Christoph Nelles <evilazrael@evilazrael.de>",
         "http://www.evilazrael.de/",
     },
+    0,  /* supportsSymlinks */
     ISO9660_openArchive,        /* openArchive() method    */
     ISO9660_enumerateFiles,     /* enumerateFiles() method */
     ISO9660_openRead,           /* openRead() method       */
--- a/src/archiver_lzma.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_lzma.c	Thu Nov 29 11:47:16 2012 -0500
@@ -532,7 +532,7 @@
 
 
 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 @@
         "Dennis Schridde <devurandom@gmx.net>",
         "http://icculus.org/physfs/",
     },
+    0,  /* supportsSymlinks */
     LZMA_openArchive,        /* openArchive() method    */
     LZMA_enumerateFiles,     /* enumerateFiles() method */
     LZMA_openRead,           /* openRead() method       */
--- a/src/archiver_mvl.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_mvl.c	Thu Nov 29 11:47:16 2012 -0500
@@ -87,6 +87,7 @@
         "Bradley Bell <btb@icculus.org>",
         "http://icculus.org/physfs/",
     },
+    0,  /* supportsSymlinks */
     MVL_openArchive,        /* openArchive() method    */
     UNPK_enumerateFiles,     /* enumerateFiles() method */
     UNPK_openRead,           /* openRead() method       */
--- a/src/archiver_qpak.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_qpak.c	Thu Nov 29 11:47:16 2012 -0500
@@ -103,6 +103,7 @@
         "Ryan C. Gordon <icculus@icculus.org>",
         "http://icculus.org/physfs/",
     },
+    0,  /* supportsSymlinks */
     QPAK_openArchive,       /* openArchive() method    */
     UNPK_enumerateFiles,    /* enumerateFiles() method */
     UNPK_openRead,          /* openRead() method       */
--- a/src/archiver_slb.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_slb.c	Thu Nov 29 11:47:16 2012 -0500
@@ -108,6 +108,7 @@
         "Aleksi Nurmi <aleksi.nurmi@gmail.com>",
         "http://bitbucket.org/ahnurmi/",
     },
+    0,  /* supportsSymlinks */
     SLB_openArchive,        /* openArchive() method    */
     UNPK_enumerateFiles,    /* enumerateFiles() method */
     UNPK_openRead,          /* openRead() method       */
--- a/src/archiver_unpacked.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_unpacked.c	Thu Nov 29 11:47:16 2012 -0500
@@ -243,7 +243,7 @@
 
 
 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);
--- a/src/archiver_wad.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_wad.c	Thu Nov 29 11:47:16 2012 -0500
@@ -111,6 +111,7 @@
         "Travis Wells <traviswells@mchsi.com>",
         "http://www.3dmm2.com/doom/",
     },
+    0,  /* supportsSymlinks */
     WAD_openArchive,        /* openArchive() method    */
     UNPK_enumerateFiles,     /* enumerateFiles() method */
     UNPK_openRead,           /* openRead() method       */
--- a/src/archiver_zip.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/archiver_zip.c	Thu Nov 29 11:47:16 2012 -0500
@@ -1488,7 +1488,7 @@
 
 
 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 @@
         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 @@
         "Ryan C. Gordon <icculus@icculus.org>",
         "http://icculus.org/physfs/",
     },
+    1,  /* supportsSymlinks */
     ZIP_openArchive,        /* openArchive() method    */
     ZIP_enumerateFiles,     /* enumerateFiles() method */
     ZIP_openRead,           /* openRead() method       */
--- a/src/physfs.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/physfs.c	Thu Nov 29 11:47:16 2012 -0500
@@ -2245,6 +2245,40 @@
 } /* 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 @@
     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 @@
 
             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);
--- a/src/physfs.h	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/physfs.h	Thu Nov 29 11:47:16 2012 -0500
@@ -3408,14 +3408,11 @@
      * 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);
 
     /**
--- a/src/physfs_internal.h	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/physfs_internal.h	Thu Nov 29 11:47:16 2012 -0500
@@ -301,7 +301,7 @@
 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 @@
  *  metaentries should always be ignored.
  */
 void __PHYSFS_platformEnumerateFiles(const char *dirname,
-                                     int omitSymLinks,
                                      PHYSFS_EnumFilesCallback callback,
                                      const char *origdir,
                                      void *callbackdata);
--- a/src/platform_posix.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/platform_posix.c	Thu Nov 29 11:47:16 2012 -0500
@@ -122,31 +122,13 @@
 
 
 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 @@
     {
         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 */
 
--- a/src/platform_windows.c	Thu Nov 29 11:45:01 2012 -0500
+++ b/src/platform_windows.c	Thu Nov 29 11:47:16 2012 -0500
@@ -487,7 +487,6 @@
 
 
 void __PHYSFS_platformEnumerateFiles(const char *dirname,
-                                     int omitSymLinks,
                                      PHYSFS_EnumFilesCallback callback,
                                      const char *origdir,
                                      void *callbackdata)
@@ -538,8 +537,6 @@
             continue;
         if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0'))
             continue;
-        if ((omitSymLinks) && (isSymlinkAttrs(attr, tag)))
-            continue;
 
         utf8 = unicodeToUtf8Heap(fn);
         if (utf8 != NULL)