Просмотр исходного кода

Centralize responsibility for filtering symlinks during enumeration.

Ryan C. Gordon 13 лет назад
Родитель
Сommit
16ee8355db

+ 3 - 3
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,
 static void DIR_enumerateFiles(void *opaque, const char *dname,
-                               int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+                               PHYSFS_EnumFilesCallback cb,
                                const char *origdir, void *callbackdata)
                                const char *origdir, void *callbackdata)
 {
 {
     char *d;
     char *d;
@@ -75,8 +75,7 @@ static void DIR_enumerateFiles(void *opaque, const char *dname,
     CVT_TO_DEPENDENT(d, opaque, dname);
     CVT_TO_DEPENDENT(d, opaque, dname);
     if (d != NULL)
     if (d != NULL)
     {
     {
-        __PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
-                                        origdir, callbackdata);
+        __PHYSFS_platformEnumerateFiles(d, cb, origdir, callbackdata);
         __PHYSFS_smallFree(d);
         __PHYSFS_smallFree(d);
     } /* if */
     } /* if */
 } /* DIR_enumerateFiles */
 } /* DIR_enumerateFiles */
@@ -187,6 +186,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
         "Ryan C. Gordon <icculus@icculus.org>",
         "Ryan C. Gordon <icculus@icculus.org>",
         "http://icculus.org/physfs/",
         "http://icculus.org/physfs/",
     },
     },
+    1,  /* supportsSymlinks */
     DIR_openArchive,        /* openArchive() method    */
     DIR_openArchive,        /* openArchive() method    */
     DIR_enumerateFiles,     /* enumerateFiles() method */
     DIR_enumerateFiles,     /* enumerateFiles() method */
     DIR_openRead,           /* openRead() method       */
     DIR_openRead,           /* openRead() method       */

+ 1 - 0
src/archiver_grp.c

@@ -94,6 +94,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
         "Ryan C. Gordon <icculus@icculus.org>",
         "Ryan C. Gordon <icculus@icculus.org>",
         "http://icculus.org/physfs/",
         "http://icculus.org/physfs/",
     },
     },
+    0,  /* supportsSymlinks */
     GRP_openArchive,        /* openArchive() method    */
     GRP_openArchive,        /* openArchive() method    */
     UNPK_enumerateFiles,    /* enumerateFiles() method */
     UNPK_enumerateFiles,    /* enumerateFiles() method */
     UNPK_openRead,          /* openRead() method       */
     UNPK_openRead,          /* openRead() method       */

+ 1 - 0
src/archiver_hog.c

@@ -100,6 +100,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
         "Bradley Bell <btb@icculus.org>",
         "Bradley Bell <btb@icculus.org>",
         "http://icculus.org/physfs/",
         "http://icculus.org/physfs/",
     },
     },
+    0,  /* supportsSymlinks */
     HOG_openArchive,         /* openArchive() method    */
     HOG_openArchive,         /* openArchive() method    */
     UNPK_enumerateFiles,     /* enumerateFiles() method */
     UNPK_enumerateFiles,     /* enumerateFiles() method */
     UNPK_openRead,           /* openRead() method       */
     UNPK_openRead,           /* openRead() method       */

+ 1 - 1
src/archiver_iso9660.c

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

+ 2 - 1
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,
 static void LZMA_enumerateFiles(void *opaque, const char *dname,
-                                int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+                                PHYSFS_EnumFilesCallback cb,
                                 const char *origdir, void *callbackdata)
                                 const char *origdir, void *callbackdata)
 {
 {
     size_t dlen = strlen(dname),
     size_t dlen = strlen(dname),
@@ -685,6 +685,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
         "Dennis Schridde <devurandom@gmx.net>",
         "Dennis Schridde <devurandom@gmx.net>",
         "http://icculus.org/physfs/",
         "http://icculus.org/physfs/",
     },
     },
+    0,  /* supportsSymlinks */
     LZMA_openArchive,        /* openArchive() method    */
     LZMA_openArchive,        /* openArchive() method    */
     LZMA_enumerateFiles,     /* enumerateFiles() method */
     LZMA_enumerateFiles,     /* enumerateFiles() method */
     LZMA_openRead,           /* openRead() method       */
     LZMA_openRead,           /* openRead() method       */

+ 1 - 0
src/archiver_mvl.c

@@ -87,6 +87,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
         "Bradley Bell <btb@icculus.org>",
         "Bradley Bell <btb@icculus.org>",
         "http://icculus.org/physfs/",
         "http://icculus.org/physfs/",
     },
     },
+    0,  /* supportsSymlinks */
     MVL_openArchive,        /* openArchive() method    */
     MVL_openArchive,        /* openArchive() method    */
     UNPK_enumerateFiles,     /* enumerateFiles() method */
     UNPK_enumerateFiles,     /* enumerateFiles() method */
     UNPK_openRead,           /* openRead() method       */
     UNPK_openRead,           /* openRead() method       */

+ 1 - 0
src/archiver_qpak.c

@@ -103,6 +103,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
         "Ryan C. Gordon <icculus@icculus.org>",
         "Ryan C. Gordon <icculus@icculus.org>",
         "http://icculus.org/physfs/",
         "http://icculus.org/physfs/",
     },
     },
+    0,  /* supportsSymlinks */
     QPAK_openArchive,       /* openArchive() method    */
     QPAK_openArchive,       /* openArchive() method    */
     UNPK_enumerateFiles,    /* enumerateFiles() method */
     UNPK_enumerateFiles,    /* enumerateFiles() method */
     UNPK_openRead,          /* openRead() method       */
     UNPK_openRead,          /* openRead() method       */

+ 1 - 0
src/archiver_slb.c

@@ -108,6 +108,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_SLB =
         "Aleksi Nurmi <aleksi.nurmi@gmail.com>",
         "Aleksi Nurmi <aleksi.nurmi@gmail.com>",
         "http://bitbucket.org/ahnurmi/",
         "http://bitbucket.org/ahnurmi/",
     },
     },
+    0,  /* supportsSymlinks */
     SLB_openArchive,        /* openArchive() method    */
     SLB_openArchive,        /* openArchive() method    */
     UNPK_enumerateFiles,    /* enumerateFiles() method */
     UNPK_enumerateFiles,    /* enumerateFiles() method */
     UNPK_openRead,          /* openRead() method       */
     UNPK_openRead,          /* openRead() method       */

+ 1 - 1
src/archiver_unpacked.c

@@ -243,7 +243,7 @@ static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
 
 
 
 
 void UNPK_enumerateFiles(void *opaque, const char *dname,
 void UNPK_enumerateFiles(void *opaque, const char *dname,
-                         int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+                         PHYSFS_EnumFilesCallback cb,
                          const char *origdir, void *callbackdata)
                          const char *origdir, void *callbackdata)
 {
 {
     UNPKinfo *info = ((UNPKinfo *) opaque);
     UNPKinfo *info = ((UNPKinfo *) opaque);

+ 1 - 0
src/archiver_wad.c

@@ -111,6 +111,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
         "Travis Wells <traviswells@mchsi.com>",
         "Travis Wells <traviswells@mchsi.com>",
         "http://www.3dmm2.com/doom/",
         "http://www.3dmm2.com/doom/",
     },
     },
+    0,  /* supportsSymlinks */
     WAD_openArchive,        /* openArchive() method    */
     WAD_openArchive,        /* openArchive() method    */
     UNPK_enumerateFiles,     /* enumerateFiles() method */
     UNPK_enumerateFiles,     /* enumerateFiles() method */
     UNPK_openRead,           /* openRead() method       */
     UNPK_openRead,           /* openRead() method       */

+ 2 - 4
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,
 static void ZIP_enumerateFiles(void *opaque, const char *dname,
-                               int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+                               PHYSFS_EnumFilesCallback cb,
                                const char *origdir, void *callbackdata)
                                const char *origdir, void *callbackdata)
 {
 {
     ZIPinfo *info = ((ZIPinfo *) opaque);
     ZIPinfo *info = ((ZIPinfo *) opaque);
@@ -1510,9 +1510,6 @@ static void ZIP_enumerateFiles(void *opaque, const char *dname,
         char *e = info->entries[i].name;
         char *e = info->entries[i].name;
         if ((dlen) && ((strncmp(e, dname, dlen) != 0) || (e[dlen] != '/')))
         if ((dlen) && ((strncmp(e, dname, dlen) != 0) || (e[dlen] != '/')))
             break;  /* past end of this dir; we're done. */
             break;  /* past end of this dir; we're done. */
-
-        if ((omitSymLinks) && (zip_entry_is_symlink(&info->entries[i])))
-            i++;
         else
         else
         {
         {
             char *add = e + dlen_inc;
             char *add = e + dlen_inc;
@@ -1701,6 +1698,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_ZIP =
         "Ryan C. Gordon <icculus@icculus.org>",
         "Ryan C. Gordon <icculus@icculus.org>",
         "http://icculus.org/physfs/",
         "http://icculus.org/physfs/",
     },
     },
+    1,  /* supportsSymlinks */
     ZIP_openArchive,        /* openArchive() method    */
     ZIP_openArchive,        /* openArchive() method    */
     ZIP_enumerateFiles,     /* enumerateFiles() method */
     ZIP_enumerateFiles,     /* enumerateFiles() method */
     ZIP_openRead,           /* openRead() method       */
     ZIP_openRead,           /* openRead() method       */

+ 55 - 4
src/physfs.c

@@ -2245,6 +2245,40 @@ static void enumerateFromMountPoint(DirHandle *i, const char *arcfname,
 } /* enumerateFromMountPoint */
 } /* 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. */
 /* !!! FIXME: this should report error conditions. */
 void PHYSFS_enumerateFilesCallback(const char *_fname,
 void PHYSFS_enumerateFilesCallback(const char *_fname,
                                    PHYSFS_EnumFilesCallback callback,
                                    PHYSFS_EnumFilesCallback callback,
@@ -2263,10 +2297,17 @@ void PHYSFS_enumerateFilesCallback(const char *_fname,
     if (sanitizePlatformIndependentPath(_fname, fname))
     if (sanitizePlatformIndependentPath(_fname, fname))
     {
     {
         DirHandle *i;
         DirHandle *i;
-        int noSyms;
+        SymlinkFilterData filterdata;
 
 
         __PHYSFS_platformGrabMutex(stateLock);
         __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)
         for (i = searchPath; i != NULL; i = i->next)
         {
         {
             char *arcfname = fname;
             char *arcfname = fname;
@@ -2275,8 +2316,18 @@ void PHYSFS_enumerateFilesCallback(const char *_fname,
 
 
             else if (verifyPath(i, &arcfname, 0))
             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 */
             } /* else if */
         } /* for */
         } /* for */
         __PHYSFS_platformReleaseMutex(stateLock);
         __PHYSFS_platformReleaseMutex(stateLock);

+ 1 - 4
src/physfs.h

@@ -3408,14 +3408,11 @@ typedef struct PHYSFS_Archiver
      * List all files in (dirname). Each file is passed to (cb),
      * List all files in (dirname). Each file is passed to (cb),
      *  where a copy is made if appropriate, so you should dispose of
      *  where a copy is made if appropriate, so you should dispose of
      *  it properly upon return from the callback.
      *  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.
      * If you have a failure, report as much as you can.
      *  (dirname) is in platform-independent notation.
      *  (dirname) is in platform-independent notation.
      */
      */
-
-// !!! FIXME: get rid of this omitsymlinks nonsense.
     void (*enumerateFiles)(void *opaque, const char *dirname,
     void (*enumerateFiles)(void *opaque, const char *dirname,
-                           int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+                           PHYSFS_EnumFilesCallback cb,
                            const char *origdir, void *callbackdata);
                            const char *origdir, void *callbackdata);
 
 
     /**
     /**

+ 1 - 2
src/physfs_internal.h

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

+ 1 - 45
src/platform_posix.c

@@ -122,31 +122,13 @@ char *__PHYSFS_platformCalcUserDir(void)
 
 
 
 
 void __PHYSFS_platformEnumerateFiles(const char *dirname,
 void __PHYSFS_platformEnumerateFiles(const char *dirname,
-                                     int omitSymLinks,
                                      PHYSFS_EnumFilesCallback callback,
                                      PHYSFS_EnumFilesCallback callback,
                                      const char *origdir,
                                      const char *origdir,
                                      void *callbackdata)
                                      void *callbackdata)
 {
 {
     DIR *dir;
     DIR *dir;
     struct dirent *ent;
     struct dirent *ent;
-    int bufsize = 0;
     char *buf = NULL;
     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;
     errno = 0;
     dir = opendir(dirname);
     dir = opendir(dirname);
@@ -160,35 +142,9 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
     {
     {
         if (strcmp(ent->d_name, ".") == 0)
         if (strcmp(ent->d_name, ".") == 0)
             continue;
             continue;
-
-        if (strcmp(ent->d_name, "..") == 0)
+        else if (strcmp(ent->d_name, "..") == 0)
             continue;
             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);
         callback(callbackdata, origdir, ent->d_name);
     } /* while */
     } /* while */
 
 

+ 0 - 3
src/platform_windows.c

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