Added first work on PHYSFS_stat() API (thanks, Christoph!).
authorRyan C. Gordon <icculus@icculus.org>
Sun, 14 Feb 2010 23:07:19 -0500
changeset 1052 f87b0b7cca8e
parent 1051 42fef01c55d6
child 1053 a277a93ac1aa
Added first work on PHYSFS_stat() API (thanks, Christoph!).
docs/CREDITS.txt
extras/physfs-swig.i
src/archiver_dir.c
src/archiver_grp.c
src/archiver_hog.c
src/archiver_lzma.c
src/archiver_mvl.c
src/archiver_qpak.c
src/archiver_wad.c
src/archiver_zip.c
src/physfs.c
src/physfs.h
src/physfs_internal.h
src/platform_os2.c
src/platform_pocketpc.c
src/platform_posix.c
src/platform_windows.c
--- a/docs/CREDITS.txt	Thu Feb 04 04:46:14 2010 -0500
+++ b/docs/CREDITS.txt	Sun Feb 14 23:07:19 2010 -0500
@@ -105,6 +105,9 @@
 Bug fixes:
     Patrice Mandin
 
+PHYSFS_stat() API:
+    Christoph Nelles
+
 Other stuff:
     Your name here! Patches go to icculus@icculus.org ...
 
--- a/extras/physfs-swig.i	Thu Feb 04 04:46:14 2010 -0500
+++ b/extras/physfs-swig.i	Sun Feb 14 23:07:19 2010 -0500
@@ -83,6 +83,7 @@
 %rename(symbolicLinksPermitted) PHYSFS_symbolicLinksPermitted;
 %rename(mount) PHYSFS_mount;
 %rename(getMountPoint) PHYSFS_getMountPoint;
+%rename(stat) PHYSFS_stat;
 #endif  /* SWIGPERL */
 
 %include "../src/physfs.h"
--- a/src/archiver_dir.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/archiver_dir.c	Sun Feb 14 23:07:19 2010 -0500
@@ -169,6 +169,20 @@
 } /* DIR_getLastModTime */
 
 
+static int DIR_stat(dvoid *opaque, const char *name, PHYSFS_Stat *st)
+{
+    char *d = __PHYSFS_platformCvtToDependent((char *)opaque, name, NULL);
+    int retval = -1;
+
+    BAIL_IF_MACRO(d == NULL, NULL, -1);
+
+    retval = __PHYSFS_platformStat(d, st);
+
+    allocator.Free(d);
+    return(retval);
+} /* DIR_stat */
+
+
 static fvoid *doOpen(dvoid *opaque, const char *name,
                      void *(*openFunc)(const char *filename),
                      int *fileExists)
@@ -261,6 +275,7 @@
     DIR_openArchive,        /* openArchive() method    */
     DIR_enumerateFiles,     /* enumerateFiles() method */
     DIR_exists,             /* exists() method         */
+    DIR_stat,               /* stat() method           */
     DIR_isDirectory,        /* isDirectory() method    */
     DIR_isSymLink,          /* isSymLink() method      */
     DIR_getLastModTime,     /* getLastModTime() method */
--- a/src/archiver_grp.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/archiver_grp.c	Sun Feb 14 23:07:19 2010 -0500
@@ -384,6 +384,12 @@
 } /* GRP_getLastModTime */
 
 
+static int GRP_stat(dvoid *opaque, const char *name, PHYSFS_Stat *st)
+{
+    return -1;  /* !!! FIXME: write me */
+} /* GRP_stat */
+
+
 static fvoid *GRP_openRead(dvoid *opaque, const char *fnm, int *fileExists)
 {
     GRPinfo *info = (GRPinfo *) opaque;
@@ -451,6 +457,7 @@
     GRP_openArchive,        /* openArchive() method    */
     GRP_enumerateFiles,     /* enumerateFiles() method */
     GRP_exists,             /* exists() method         */
+    GRP_stat,               /* stat() method           */
     GRP_isDirectory,        /* isDirectory() method    */
     GRP_isSymLink,          /* isSymLink() method      */
     GRP_getLastModTime,     /* getLastModTime() method */
--- a/src/archiver_hog.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/archiver_hog.c	Sun Feb 14 23:07:19 2010 -0500
@@ -423,6 +423,12 @@
 } /* HOG_getLastModTime */
 
 
+static int HOG_stat(dvoid *opaque, const char *name, PHYSFS_Stat *st)
+{
+    return -1;  /* !!! FIXME: write me */
+} /* HOG_stat */
+
+
 static fvoid *HOG_openRead(dvoid *opaque, const char *fnm, int *fileExists)
 {
     HOGinfo *info = ((HOGinfo *) opaque);
@@ -490,6 +496,7 @@
     HOG_openArchive,        /* openArchive() method    */
     HOG_enumerateFiles,     /* enumerateFiles() method */
     HOG_exists,             /* exists() method         */
+    HOG_stat,               /* stat() method           */
     HOG_isDirectory,        /* isDirectory() method    */
     HOG_isSymLink,          /* isSymLink() method      */
     HOG_getLastModTime,     /* getLastModTime() method */
--- a/src/archiver_lzma.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/archiver_lzma.c	Sun Feb 14 23:07:19 2010 -0500
@@ -623,6 +623,12 @@
 } /* LZMA_getLastModTime */
 
 
+static int LZMA_stat(dvoid *opaque, const char *name, PHYSFS_Stat *st)
+{
+    return -1;  /* !!! FIXME: write me */
+} /* LZMA_stat */
+
+
 static int LZMA_isDirectory(dvoid *opaque, const char *name, int *fileExists)
 {
     LZMAarchive *archive = (LZMAarchive *) opaque;
@@ -712,6 +718,7 @@
     LZMA_openArchive,        /* openArchive() method    */
     LZMA_enumerateFiles,     /* enumerateFiles() method */
     LZMA_exists,             /* exists() method         */
+    LZMA_stat,               /* stat() method           */
     LZMA_isDirectory,        /* isDirectory() method    */
     LZMA_isSymLink,          /* isSymLink() method      */
     LZMA_getLastModTime,     /* getLastModTime() method */
--- a/src/archiver_mvl.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/archiver_mvl.c	Sun Feb 14 23:07:19 2010 -0500
@@ -380,6 +380,12 @@
 } /* MVL_getLastModTime */
 
 
+static int MVL_stat(dvoid *opaque, const char *name, PHYSFS_Stat *st)
+{
+    return -1;  /* !!! FIXME: write me */
+} /* MVL_stat */
+
+
 static fvoid *MVL_openRead(dvoid *opaque, const char *fnm, int *fileExists)
 {
     MVLinfo *info = ((MVLinfo *) opaque);
@@ -447,6 +453,7 @@
     MVL_openArchive,        /* openArchive() method    */
     MVL_enumerateFiles,     /* enumerateFiles() method */
     MVL_exists,             /* exists() method         */
+    MVL_stat,               /* stat() method           */
     MVL_isDirectory,        /* isDirectory() method    */
     MVL_isSymLink,          /* isSymLink() method      */
     MVL_getLastModTime,     /* getLastModTime() method */
--- a/src/archiver_qpak.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/archiver_qpak.c	Sun Feb 14 23:07:19 2010 -0500
@@ -537,6 +537,12 @@
 } /* QPAK_getLastModTime */
 
 
+static int QPAK_stat(dvoid *opaque, const char *name, PHYSFS_Stat *st)
+{
+    return -1;  /* !!! FIXME: write me */
+} /* QPAK_stat */
+
+
 static fvoid *QPAK_openRead(dvoid *opaque, const char *fnm, int *fileExists)
 {
     QPAKinfo *info = ((QPAKinfo *) opaque);
@@ -606,6 +612,7 @@
     QPAK_openArchive,        /* openArchive() method    */
     QPAK_enumerateFiles,     /* enumerateFiles() method */
     QPAK_exists,             /* exists() method         */
+    QPAK_stat,               /* stat() method           */
     QPAK_isDirectory,        /* isDirectory() method    */
     QPAK_isSymLink,          /* isSymLink() method      */
     QPAK_getLastModTime,     /* getLastModTime() method */
--- a/src/archiver_wad.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/archiver_wad.c	Sun Feb 14 23:07:19 2010 -0500
@@ -443,6 +443,12 @@
 } /* WAD_getLastModTime */
 
 
+static int WAD_stat(dvoid *opaque, const char *name, PHYSFS_Stat *st)
+{
+    return -1;  /* !!! FIXME: write me */
+} /* WAD_stat */
+
+
 static fvoid *WAD_openRead(dvoid *opaque, const char *fnm, int *fileExists)
 {
     WADinfo *info = ((WADinfo *) opaque);
@@ -510,6 +516,7 @@
     WAD_openArchive,        /* openArchive() method    */
     WAD_enumerateFiles,     /* enumerateFiles() method */
     WAD_exists,             /* exists() method         */
+    WAD_stat,               /* stat() method           */
     WAD_isDirectory,        /* isDirectory() method    */
     WAD_isSymLink,          /* isSymLink() method      */
     WAD_getLastModTime,     /* getLastModTime() method */
--- a/src/archiver_zip.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/archiver_zip.c	Sun Feb 14 23:07:19 2010 -0500
@@ -1264,6 +1264,12 @@
 } /* ZIP_getLastModTime */
 
 
+static int ZIP_stat(dvoid *opaque, const char *name, PHYSFS_Stat *st)
+{
+    return -1;  /* !!! FIXME: write me */
+} /* ZIP_stat */
+
+
 static int ZIP_isDirectory(dvoid *opaque, const char *name, int *fileExists)
 {
     ZIPinfo *info = (ZIPinfo *) opaque;
@@ -1422,6 +1428,7 @@
     ZIP_openArchive,        /* openArchive() method    */
     ZIP_enumerateFiles,     /* enumerateFiles() method */
     ZIP_exists,             /* exists() method         */
+    ZIP_stat,               /* stat() method           */
     ZIP_isDirectory,        /* isDirectory() method    */
     ZIP_isSymLink,          /* isSymLink() method      */
     ZIP_getLastModTime,     /* getLastModTime() method */
--- a/src/physfs.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/physfs.c	Sun Feb 14 23:07:19 2010 -0500
@@ -1620,6 +1620,50 @@
     return (PHYSFS_getRealDir(fname) != NULL);
 } /* PHYSFS_exists */
 
+int PHYSFS_stat(const char *_fname, PHYSFS_Stat *st)
+{
+    char *fname;
+    size_t len;
+    int retval = -1;
+
+    BAIL_IF_MACRO(_fname == NULL, ERR_INVALID_ARGUMENT, -1);
+    BAIL_IF_MACRO(st == NULL, ERR_INVALID_ARGUMENT, -1);
+
+    memset(st, 0, sizeof(PHYSFS_Stat));
+    len = strlen(_fname) + 1;
+    fname = (char *) __PHYSFS_smallAlloc(len);
+    BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, -1);
+
+    if (sanitizePlatformIndependentPath(_fname, fname))
+    {
+        if (*fname == '\0')  /* eh...punt if it's the root dir. */
+        {
+            retval = 0;  /* !!! FIXME: Maybe this should be an error? */
+            st->is_dir = 1;
+        } /* if */
+        else
+        {
+            DirHandle *i;
+            int exists = 0;
+            __PHYSFS_platformGrabMutex(stateLock);
+            for (i = searchPath; ((i != NULL) && (!exists)); i = i->next)
+            {
+                char *arcfname = fname;
+                exists = partOfMountPoint(i, arcfname);
+                if (exists)
+                    retval = 1; /* !!! FIXME: What's the right value? */
+                else if (verifyPath(i, &arcfname, 0))
+                {
+                   retval = i->funcs->stat(i->opaque, arcfname, st);
+                } /* else if */
+            } /* for */
+            __PHYSFS_platformReleaseMutex(stateLock);
+        } /* else */
+    } /* if */
+
+    __PHYSFS_smallFree(fname);
+    return(retval);
+}
 
 PHYSFS_sint64 PHYSFS_getLastModTime(const char *_fname)
 {
--- a/src/physfs.h	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/physfs.h	Sun Feb 14 23:07:19 2010 -0500
@@ -2463,6 +2463,42 @@
 #endif  /* SWIG */
 
 
+/**
+ * \struct PHYSFS_Stat
+ * \brief Information on a file in a PhysicsFS filesystem.
+ *
+ * Created as a way to get a file's information without repeated calls and
+ *  without having to open the file.
+ *
+ * \sa PHYSFS_stat
+ */
+typedef struct PHYSFS_Stat
+{
+    int is_dir;
+    int is_symlink;
+    PHYSFS_sint64 size;
+    PHYSFS_sint64 atime;
+    PHYSFS_sint64 mtime;
+    PHYSFS_sint64 ctime;
+} PHYSFS_Stat;
+
+
+/**
+ * \fn int PHYSFS_stat(const char *fname, PHYSFS_Stat * st)
+ * \brief Get information on a file in the search path.
+ *
+ *    \param fname filename in platform-independent notation.
+ *    \param st pointer to an PHYSFS_Stat structure.
+ *   \return 0 on success (file exists and information retreived successfully),
+ *           non-zero otherwise.
+ *
+ * !!! FIXME: have to distinguish between "unsupported", "missing" and
+ * !!! FIXME:  "failure" results.
+ *
+ * \sa PHYSFS_Stat
+ */
+PHYSFS_DECL int PHYSFS_stat(const char *fname, PHYSFS_Stat *st);
+
 /* Everything above this line is part of the PhysicsFS 2.1 API. */
 
 
--- a/src/physfs_internal.h	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/physfs_internal.h	Sun Feb 14 23:07:19 2010 -0500
@@ -774,6 +774,12 @@
     int (*exists)(dvoid *opaque, const char *name);
 
         /*
+         * Returns zero if filename can be opened for reading and
+         *  information was retreived. Non-zero otherwise.
+         */
+    int (*stat)(dvoid *opaque, const char *name, PHYSFS_Stat *st);
+
+        /*
          * Returns non-zero if filename is really a directory.
          *  This filename is in platform-independent notation.
          *  Symlinks should be followed; if what the symlink points
@@ -1346,6 +1352,12 @@
 
 
 /*
+ * !!! FIXME: comment me.
+ */
+int __PHYSFS_platformStat(const char *fname, PHYSFS_Stat *st);
+
+
+/*
  * Convert (dirName) to platform-dependent notation, then prepend (prepend)
  *  and append (append) to the converted string.
  *
--- a/src/platform_os2.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/platform_os2.c	Sun Feb 14 23:07:19 2010 -0500
@@ -322,6 +322,12 @@
 } /* __PHYSFS_platformIsDirectory */
 
 
+int __PHYSFS_platformStat(const char *fname, PHYSFS_Stat *st)
+{
+    return -1;  /* !!! FIXME: write me */
+} /* __PHYSFS_platformStat */
+
+
 /* !!! FIXME: can we lose the malloc here? */
 char *__PHYSFS_platformCvtToDependent(const char *prepend,
                                       const char *dirName,
--- a/src/platform_pocketpc.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/platform_pocketpc.c	Sun Feb 14 23:07:19 2010 -0500
@@ -201,6 +201,12 @@
 } /* __PHYSFS_platformIsDirectory */
 
 
+int __PHYSFS_platformStat(const char *fname, PHYSFS_Stat *st)
+{
+    return -1;  /* !!! FIXME: write me */
+} /* __PHYSFS_platformStat */
+
+
 char *__PHYSFS_platformCvtToDependent(const char *prepend,
                                       const char *dirName,
                                       const char *append)
--- a/src/platform_posix.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/platform_posix.c	Sun Feb 14 23:07:19 2010 -0500
@@ -127,6 +127,27 @@
 } /* __PHYSFS_platformIsDirectory */
 
 
+int __PHYSFS_platformStat(const char *fname, PHYSFS_Stat *st)
+{
+    int retval = 0;
+    struct stat pstat;
+
+    /* !!! FIXME: lstat()? */
+    retval = stat(fname, &pstat);
+    if (retval == 0)
+    {
+        st->size = pstat.st_size;
+        st->mtime = pstat.st_mtime;
+        st->atime = pstat.st_atime;
+        st->ctime = pstat.st_ctime;
+        st->is_symlink = S_ISLNK(pstat.st_mode) ? 1 : 0;
+        st->is_dir = S_ISDIR(pstat.st_mode) ? 1 : 0;
+    } /* if */
+
+    return(retval);
+} /* __PHYSFS_platformStat */
+
+
 char *__PHYSFS_platformCvtToDependent(const char *prepend,
                                       const char *dirName,
                                       const char *append)
--- a/src/platform_windows.c	Thu Feb 04 04:46:14 2010 -0500
+++ b/src/platform_windows.c	Sun Feb 14 23:07:19 2010 -0500
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <ctype.h>
 #include <time.h>
+#include <sys/stat.h>
 
 #include "physfs_internal.h"
 
@@ -587,6 +588,29 @@
     return retval;
 } /* __PHYSFS_platformExists */
 
+int __PHYSFS_platformStat(const char *fname, PHYSFS_Stat *st)
+{
+    int retval = 0;
+    LPWSTR wpath;
+    struct _stat64 pstat;
+    UTF8_TO_UNICODE_STACK_MACRO(wpath, fname);
+    BAIL_IF_MACRO(wpath == NULL, ERR_OUT_OF_MEMORY, -1);
+    
+    retval = _wstat64(wpath, &pstat);
+    if (retval == 0)
+    {
+        st->size = pstat.st_size;
+        st->mtime = pstat.st_mtime;
+        st->atime = pstat.st_atime;
+        st->ctime = pstat.st_ctime;
+        st->is_dir = (pstat.st_mode & _S_IFDIR) ? 1:0;
+        st->is_symlink = 0;
+    } /* if */
+
+    __PHYSFS_smallFree(wpath);
+    return(retval);
+} /*  __PHYSFS_platformStat */
+
 
 static int isSymlinkAttrs(const DWORD attr, const DWORD tag)
 {