Bunch of tedious corrections, optimizations, and cleanups.
authorRyan C. Gordon <icculus@icculus.org>
Wed, 21 Aug 2002 02:59:15 +0000
changeset 467 99664d9842cb
parent 466 1e3b97bcdee4
child 468 ac9c7e9626d3
Bunch of tedious corrections, optimizations, and cleanups.
archivers/dir.c
archivers/grp.c
archivers/qpak.c
archivers/zip.c
physfs.c
physfs_internal.h
platform/posix.c
platform/win32.c
--- a/archivers/dir.c	Wed Aug 21 02:58:30 2002 +0000
+++ b/archivers/dir.c	Wed Aug 21 02:59:15 2002 +0000
@@ -24,6 +24,10 @@
                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 static PHYSFS_sint64 DIR_write(FileHandle *handle, const void *buffer,
                                PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+static PHYSFS_sint64 DIR_dummyRead(FileHandle *handle, void *buffer,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+static PHYSFS_sint64 DIR_dummyWrite(FileHandle *handle, const void *buffer,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 static int DIR_eof(FileHandle *handle);
 static PHYSFS_sint64 DIR_tell(FileHandle *handle);
 static int DIR_seek(FileHandle *handle, PHYSFS_uint64 offset);
@@ -35,10 +39,10 @@
                                             const char *dname,
                                             int omitSymLinks);
 static int DIR_exists(DirHandle *h, const char *name);
-static int DIR_isDirectory(DirHandle *h, const char *name);
-static int DIR_isSymLink(DirHandle *h, const char *name);
-static FileHandle *DIR_openRead(DirHandle *h, const char *filename);
-static PHYSFS_sint64 DIR_getLastModTime(DirHandle *h, const char *name);
+static int DIR_isDirectory(DirHandle *h, const char *name, int *fileExists);
+static int DIR_isSymLink(DirHandle *h, const char *name, int *fileExists);
+static FileHandle *DIR_openRead(DirHandle *h, const char *fnm, int *exist);
+static PHYSFS_sint64 DIR_getLastModTime(DirHandle *h, const char *f, int *e);
 static FileHandle *DIR_openWrite(DirHandle *h, const char *filename);
 static FileHandle *DIR_openAppend(DirHandle *h, const char *filename);
 static int DIR_remove(DirHandle *h, const char *name);
@@ -58,7 +62,7 @@
 static const FileFunctions __PHYSFS_FileFunctions_DIR =
 {
     DIR_read,       /* read() method       */
-    NULL,           /* write() method      */
+    DIR_dummyWrite, /* write() method      */
     DIR_eof,        /* eof() method        */
     DIR_tell,       /* tell() method       */
     DIR_seek,       /* seek() method       */
@@ -69,7 +73,7 @@
 
 static const FileFunctions __PHYSFS_FileFunctions_DIRW =
 {
-    NULL,           /* read() method       */
+    DIR_dummyRead,  /* read() method       */
     DIR_write,      /* write() method      */
     DIR_eof,        /* eof() method        */
     DIR_tell,       /* tell() method       */
@@ -116,6 +120,20 @@
 } /* DIR_write */
 
 
+static PHYSFS_sint64 DIR_dummyRead(FileHandle *handle, void *buffer,
+                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
+} /* DIR_dummyRead */
+
+
+static PHYSFS_sint64 DIR_dummyWrite(FileHandle *handle, const void *buffer,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
+} /* DIR_dummyWrite */
+
+
 static int DIR_eof(FileHandle *handle)
 {
     return(__PHYSFS_platformEOF(handle->opaque));
@@ -217,37 +235,45 @@
 } /* DIR_exists */
 
 
-static int DIR_isDirectory(DirHandle *h, const char *name)
+static int DIR_isDirectory(DirHandle *h, const char *name, int *fileExists)
 {
     char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
-    int retval;
+    int retval = 0;
 
     BAIL_IF_MACRO(d == NULL, NULL, 0);
-    retval = __PHYSFS_platformIsDirectory(d);
+    *fileExists = __PHYSFS_platformExists(d);
+    if (*fileExists)
+        retval = __PHYSFS_platformIsDirectory(d);
     free(d);
     return(retval);
 } /* DIR_isDirectory */
 
 
-static int DIR_isSymLink(DirHandle *h, const char *name)
+static int DIR_isSymLink(DirHandle *h, const char *name, int *fileExists)
 {
     char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
-    int retval;
+    int retval = 0;
 
     BAIL_IF_MACRO(f == NULL, NULL, 0);
-    retval = __PHYSFS_platformIsSymLink(f);
+    *fileExists = __PHYSFS_platformExists(f);
+    if (*fileExists)
+        retval = __PHYSFS_platformIsSymLink(f);
     free(f);
     return(retval);
 } /* DIR_isSymLink */
 
 
-static PHYSFS_sint64 DIR_getLastModTime(DirHandle *h, const char *name)
+static PHYSFS_sint64 DIR_getLastModTime(DirHandle *h,
+                                        const char *name,
+                                        int *fileExists)
 {
     char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
-    PHYSFS_sint64 retval;
+    PHYSFS_sint64 retval = -1;
 
     BAIL_IF_MACRO(d == NULL, NULL, 0);
-    retval = __PHYSFS_platformGetLastModTime(d);
+    *fileExists = __PHYSFS_platformExists(d);
+    if (*fileExists)
+        retval = __PHYSFS_platformGetLastModTime(d);
     free(d);
     return(retval);
 } /* DIR_getLastModTime */
@@ -255,7 +281,7 @@
 
 static FileHandle *doOpen(DirHandle *h, const char *name,
                           void *(*openFunc)(const char *filename),
-                          const FileFunctions *fileFuncs)
+                          int *fileExists, const FileFunctions *fileFuncs)
 {
     char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
     void *rc;
@@ -263,6 +289,16 @@
 
     BAIL_IF_MACRO(f == NULL, NULL, NULL);
 
+    if (fileExists != NULL)
+    {
+        *fileExists = __PHYSFS_platformExists(f);
+        if (!(*fileExists))
+        {
+            free(f);
+            return(NULL);
+        } /* if */
+    } /* if */
+
     retval = (FileHandle *) malloc(sizeof (FileHandle));
     if (!retval)
     {
@@ -287,23 +323,23 @@
 } /* doOpen */
 
 
-static FileHandle *DIR_openRead(DirHandle *h, const char *filename)
+static FileHandle *DIR_openRead(DirHandle *h, const char *fnm, int *exist)
 {
-    return(doOpen(h, filename, __PHYSFS_platformOpenRead,
+    return(doOpen(h, fnm, __PHYSFS_platformOpenRead, exist,
                   &__PHYSFS_FileFunctions_DIR));
 } /* DIR_openRead */
 
 
 static FileHandle *DIR_openWrite(DirHandle *h, const char *filename)
 {
-    return(doOpen(h, filename, __PHYSFS_platformOpenWrite,
+    return(doOpen(h, filename, __PHYSFS_platformOpenWrite, NULL,
                   &__PHYSFS_FileFunctions_DIRW));
 } /* DIR_openWrite */
 
 
 static FileHandle *DIR_openAppend(DirHandle *h, const char *filename)
 {
-    return(doOpen(h, filename, __PHYSFS_platformOpenAppend,
+    return(doOpen(h, filename, __PHYSFS_platformOpenAppend, NULL,
                   &__PHYSFS_FileFunctions_DIRW));
 } /* DIR_openAppend */
 
--- a/archivers/grp.c	Wed Aug 21 02:58:30 2002 +0000
+++ b/archivers/grp.c	Wed Aug 21 02:59:15 2002 +0000
@@ -67,6 +67,8 @@
 static void GRP_dirClose(DirHandle *h);
 static PHYSFS_sint64 GRP_read(FileHandle *handle, void *buffer,
                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+static PHYSFS_sint64 GRP_write(FileHandle *handle, const void *buffer,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 static int GRP_eof(FileHandle *handle);
 static PHYSFS_sint64 GRP_tell(FileHandle *handle);
 static int GRP_seek(FileHandle *handle, PHYSFS_uint64 offset);
@@ -78,10 +80,14 @@
                                             const char *dirname,
                                             int omitSymLinks);
 static int GRP_exists(DirHandle *h, const char *name);
-static int GRP_isDirectory(DirHandle *h, const char *name);
-static int GRP_isSymLink(DirHandle *h, const char *name);
-static PHYSFS_sint64 GRP_getLastModTime(DirHandle *h, const char *name);
-static FileHandle *GRP_openRead(DirHandle *h, const char *name);
+static int GRP_isDirectory(DirHandle *h, const char *name, int *fileExists);
+static int GRP_isSymLink(DirHandle *h, const char *name, int *fileExists);
+static PHYSFS_sint64 GRP_getLastModTime(DirHandle *h, const char *n, int *e);
+static FileHandle *GRP_openRead(DirHandle *h, const char *name, int *exist);
+static FileHandle *GRP_openWrite(DirHandle *h, const char *name);
+static FileHandle *GRP_openAppend(DirHandle *h, const char *name);
+static int GRP_remove(DirHandle *h, const char *name);
+static int GRP_mkdir(DirHandle *h, const char *name);
 
 const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_GRP =
 {
@@ -95,7 +101,7 @@
 static const FileFunctions __PHYSFS_FileFunctions_GRP =
 {
     GRP_read,       /* read() method       */
-    NULL,           /* write() method      */
+    GRP_write,      /* write() method      */
     GRP_eof,        /* eof() method        */
     GRP_tell,       /* tell() method       */
     GRP_seek,       /* seek() method       */
@@ -115,10 +121,10 @@
     GRP_isSymLink,          /* isSymLink() method      */
     GRP_getLastModTime,     /* getLastModTime() method */
     GRP_openRead,           /* openRead() method       */
-    NULL,                   /* openWrite() method      */
-    NULL,                   /* openAppend() method     */
-    NULL,                   /* remove() method         */
-    NULL,                   /* mkdir() method          */
+    GRP_openWrite,          /* openWrite() method      */
+    GRP_openAppend,         /* openAppend() method     */
+    GRP_remove,             /* remove() method         */
+    GRP_mkdir,              /* mkdir() method          */
     GRP_dirClose            /* dirClose() method       */
 };
 
@@ -154,6 +160,13 @@
 } /* GRP_read */
 
 
+static PHYSFS_sint64 GRP_write(FileHandle *handle, const void *buffer,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
+} /* GRP_write */
+
+
 static int GRP_eof(FileHandle *handle)
 {
     GRPfileinfo *finfo = (GRPfileinfo *) (handle->opaque);
@@ -427,37 +440,44 @@
 } /* GRP_exists */
 
 
-static int GRP_isDirectory(DirHandle *h, const char *name)
+static int GRP_isDirectory(DirHandle *h, const char *name, int *fileExists)
 {
+    *fileExists = GRP_exists(h, name);
     return(0);  /* never directories in a groupfile. */
 } /* GRP_isDirectory */
 
 
-static int GRP_isSymLink(DirHandle *h, const char *name)
+static int GRP_isSymLink(DirHandle *h, const char *name, int *fileExists)
 {
+    *fileExists = GRP_exists(h, name);
     return(0);  /* never symlinks in a groupfile. */
 } /* GRP_isSymLink */
 
 
-static PHYSFS_sint64 GRP_getLastModTime(DirHandle *h, const char *name)
+static PHYSFS_sint64 GRP_getLastModTime(DirHandle *h,
+                                        const char *name,
+                                        int *fileExists)
 {
     GRPinfo *info = ((GRPinfo *) h->opaque);
-    if (grp_find_entry(info, name) == NULL)
-        return(-1);  /* no such entry. */
+    PHYSFS_sint64 retval = -1;
 
-    /* Just return the time of the GRP itself in the physical filesystem. */
-    return(((GRPinfo *) h->opaque)->last_mod_time);
+    *fileExists = (grp_find_entry(info, name) != NULL);
+    if (*fileExists)  /* use time of GRP itself in the physical filesystem. */
+        retval = ((GRPinfo *) h->opaque)->last_mod_time;
+
+    return(retval);
 } /* GRP_getLastModTime */
 
 
-static FileHandle *GRP_openRead(DirHandle *h, const char *name)
+static FileHandle *GRP_openRead(DirHandle *h, const char *fnm, int *fileExists)
 {
     GRPinfo *info = ((GRPinfo *) h->opaque);
     FileHandle *retval;
     GRPfileinfo *finfo;
     GRPentry *entry;
 
-    entry = grp_find_entry(info, name);
+    entry = grp_find_entry(info, fnm);
+    *fileExists = (entry != NULL);
     BAIL_IF_MACRO(entry == NULL, NULL, NULL);
 
     retval = (FileHandle *) malloc(sizeof (FileHandle));
@@ -486,6 +506,30 @@
     return(retval);
 } /* GRP_openRead */
 
+
+static FileHandle *GRP_openWrite(DirHandle *h, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* GRP_openWrite */
+
+
+static FileHandle *GRP_openAppend(DirHandle *h, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* GRP_openAppend */
+
+
+static int GRP_remove(DirHandle *h, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
+} /* GRP_remove */
+
+
+static int GRP_mkdir(DirHandle *h, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
+} /* GRP_mkdir */
+
 #endif  /* defined PHYSFS_SUPPORTS_GRP */
 
 /* end of grp.c ... */
--- a/archivers/qpak.c	Wed Aug 21 02:58:30 2002 +0000
+++ b/archivers/qpak.c	Wed Aug 21 02:59:15 2002 +0000
@@ -73,19 +73,25 @@
 static LinkedStringList *QPAK_enumerateFiles(DirHandle *h, const char *dirname,
                                              int omitSymLinks);
 static int           QPAK_exists(DirHandle *h, const char *name);
-static int           QPAK_isDirectory(DirHandle *h, const char *name);
-static int           QPAK_isSymLink(DirHandle *h, const char *name);
-static PHYSFS_sint64 QPAK_getLastModTime(DirHandle *h, const char *name);
-static FileHandle   *QPAK_openRead(DirHandle *h, const char *name);
+static int           QPAK_isDirectory(DirHandle *h, const char *name, int *e);
+static int           QPAK_isSymLink(DirHandle *h, const char *name, int *e);
+static PHYSFS_sint64 QPAK_getLastModTime(DirHandle *h, const char *n, int *e);
+static FileHandle   *QPAK_openRead(DirHandle *h, const char *name, int *e);
+static FileHandle   *QPAK_openWrite(DirHandle *h, const char *name);
+static FileHandle   *QPAK_openAppend(DirHandle *h, const char *name);
 
 
 static PHYSFS_sint64 QPAK_read(FileHandle *handle, void *buffer,
-                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+static PHYSFS_sint64 QPAK_write(FileHandle *handle, const void *buffer,
+                                PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 static int           QPAK_eof(FileHandle *handle);
 static PHYSFS_sint64 QPAK_tell(FileHandle *handle);
 static int           QPAK_seek(FileHandle *handle, PHYSFS_uint64 offset);
 static PHYSFS_sint64 QPAK_fileLength(FileHandle *handle);
 static int           QPAK_fileClose(FileHandle *handle);
+static int           QPAK_remove(DirHandle *h, const char *name);
+static int           QPAK_mkdir(DirHandle *h, const char *name);
 
 
 const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_QPAK =
@@ -99,7 +105,7 @@
 static const FileFunctions __PHYSFS_FileFunctions_QPAK =
 {
     QPAK_read,               /* read() method       */
-    NULL,                    /* write() method      */
+    QPAK_write,              /* write() method      */
     QPAK_eof,                /* eof() method        */
     QPAK_tell,               /* tell() method       */
     QPAK_seek,               /* seek() method       */
@@ -118,10 +124,10 @@
     QPAK_isSymLink,          /* isSymLink() method      */
     QPAK_getLastModTime,     /* getLastModTime() method */
     QPAK_openRead,           /* openRead() method       */
-    NULL,                    /* openWrite() method      */
-    NULL,                    /* openAppend() method     */
-    NULL,                    /* remove() method         */
-    NULL,                    /* mkdir() method          */
+    QPAK_openWrite,          /* openWrite() method      */
+    QPAK_openAppend,         /* openAppend() method     */
+    QPAK_remove,             /* remove() method         */
+    QPAK_mkdir,              /* mkdir() method          */
     QPAK_dirClose            /* dirClose() method       */
 };
 
@@ -308,7 +314,7 @@
         } /* while */
     } /* else */
 
-    return(0);
+    BAIL_MACRO(ERR_NO_SUCH_PATH, 0);
 } /* qpak_findDirectory */
 
 
@@ -390,7 +396,7 @@
         thisFile = thisFile->next;
     } /* while */
 
-    return(0);
+    BAIL_MACRO(ERR_NO_SUCH_FILE, 0);
 } /* qpak_findEntry */
 
 
@@ -585,22 +591,45 @@
 } /* QPAK_exists */
 
 
-static int QPAK_isDirectory(DirHandle *h, const char *name)
+static int QPAK_isDirectory(DirHandle *h, const char *name, int *fileExists)
 {
     QPAKinfo *info = (QPAKinfo *) h->opaque;
-    return(qpak_findDirectory(info->root, name) != 0);
+    *fileExists = (qpak_findDirectory(info->root, name) != 0);
+    return(*fileExists);
 } /* QPAK_isDirectory */
 
 
-static int QPAK_isSymLink(DirHandle *h, const char *name)
+static int QPAK_isSymLink(DirHandle *h, const char *name, int *fileExists)
 {
+    *fileExists = QPAK_exists(h, name);
     return(0); /* we don't support symlinks for now */
 } /* QPAK_isSymlink */
 
 
-static PHYSFS_sint64 QPAK_getLastModTime(DirHandle *h, const char *name)
+static int QPAK_remove(DirHandle *h, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
+} /* QPAK_remove */
+
+
+static int QPAK_mkdir(DirHandle *h, const char *name)
 {
-    return(__PHYSFS_platformGetLastModTime(((QPAKinfo *) h->opaque)->filename));
+    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
+} /* QPAK_mkdir */
+
+
+static PHYSFS_sint64 QPAK_getLastModTime(DirHandle *h,
+                                         const char *name,
+                                         int *fileExists)
+{
+    QPAKinfo *info = (QPAKinfo *) h->opaque;
+    PHYSFS_sint64 retval = -1;
+
+    *fileExists = QPAK_exists(h, name);
+    if (*fileExists)
+        retval = __PHYSFS_platformGetLastModTime(info->filename);
+
+    return(retval);
 } /* QPAK_getLastModTime */
 
 
@@ -620,13 +649,14 @@
 } /* qpak_getFileHandle */
 
 
-static FileHandle *QPAK_openRead(DirHandle *h, const char *name)
+static FileHandle *QPAK_openRead(DirHandle *h, const char *fnm, int *fileExists)
 {
     QPAKinfo *driver = (QPAKinfo *) h->opaque;
-    QPAKentry *entry = qpak_findEntry(driver->root, name);
+    QPAKentry *entry = qpak_findEntry(driver->root, fnm);
     QPAKfileinfo *fileDriver = 0;
     FileHandle *result = 0;
 
+    *fileExists = (entry != NULL);
     if (entry == NULL)
         return(NULL);
  
@@ -658,6 +688,18 @@
 } /* QPAK_openRead */
 
 
+static FileHandle *QPAK_openWrite(DirHandle *h, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* QPAK_openWrite */
+
+
+static FileHandle *QPAK_openAppend(DirHandle *h, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* QPAK_openAppend */
+
+
 static PHYSFS_sint64 QPAK_read(FileHandle *handle, void *buffer,
                                PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
 {
@@ -678,6 +720,13 @@
 } /* QPAK_read */
 
 
+static PHYSFS_sint64 QPAK_write(FileHandle *handle, const void *buffer,
+                                PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
+} /* QPAK_write */
+
+
 static int QPAK_eof(FileHandle *handle)
 {
     QPAKfileinfo *finfo = (QPAKfileinfo *) (handle->opaque);
--- a/archivers/zip.c	Wed Aug 21 02:58:30 2002 +0000
+++ b/archivers/zip.c	Wed Aug 21 02:59:15 2002 +0000
@@ -118,6 +118,8 @@
 
 static PHYSFS_sint64 ZIP_read(FileHandle *handle, void *buffer,
                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+static PHYSFS_sint64 ZIP_write(FileHandle *handle, const void *buffer,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 static int ZIP_eof(FileHandle *handle);
 static PHYSFS_sint64 ZIP_tell(FileHandle *handle);
 static int ZIP_seek(FileHandle *handle, PHYSFS_uint64 offset);
@@ -129,12 +131,16 @@
                                             const char *dirname,
                                             int omitSymLinks);
 static int ZIP_exists(DirHandle *h, const char *name);
-static int ZIP_isDirectory(DirHandle *h, const char *name);
-static int ZIP_isSymLink(DirHandle *h, const char *name);
-static PHYSFS_sint64 ZIP_getLastModTime(DirHandle *h, const char *name);
-static FileHandle *ZIP_openRead(DirHandle *h, const char *filename);
+static int ZIP_isDirectory(DirHandle *h, const char *name, int *fileExists);
+static int ZIP_isSymLink(DirHandle *h, const char *name, int *fileExists);
+static PHYSFS_sint64 ZIP_getLastModTime(DirHandle *h, const char *n, int *e);
+static FileHandle *ZIP_openRead(DirHandle *h, const char *filename, int *e);
+static FileHandle *ZIP_openWrite(DirHandle *h, const char *filename);
+static FileHandle *ZIP_openAppend(DirHandle *h, const char *filename);
 static void ZIP_dirClose(DirHandle *h);
 static int zip_resolve(void *in, ZIPinfo *info, ZIPentry *entry);
+static int ZIP_remove(DirHandle *h, const char *name);
+static int ZIP_mkdir(DirHandle *h, const char *name);
 
 
 const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_ZIP =
@@ -148,7 +154,7 @@
 static const FileFunctions __PHYSFS_FileFunctions_ZIP =
 {
     ZIP_read,       /* read() method       */
-    NULL,           /* write() method      */
+    ZIP_write,      /* write() method      */
     ZIP_eof,        /* eof() method        */
     ZIP_tell,       /* tell() method       */
     ZIP_seek,       /* seek() method       */
@@ -168,10 +174,10 @@
     ZIP_isSymLink,          /* isSymLink() method      */
     ZIP_getLastModTime,     /* getLastModTime() method */
     ZIP_openRead,           /* openRead() method       */
-    NULL,                   /* openWrite() method      */
-    NULL,                   /* openAppend() method     */
-    NULL,                   /* remove() method         */
-    NULL,                   /* mkdir() method          */
+    ZIP_openWrite,          /* openWrite() method      */
+    ZIP_openAppend,         /* openAppend() method     */
+    ZIP_remove,             /* remove() method         */
+    ZIP_mkdir,              /* mkdir() method          */
     ZIP_dirClose            /* dirClose() method       */
 };
 
@@ -305,6 +311,13 @@
 } /* ZIP_read */
 
 
+static PHYSFS_sint64 ZIP_write(FileHandle *handle, const void *buf,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
+} /* ZIP_write */
+
+
 static int ZIP_eof(FileHandle *handle)
 {
     ZIPfileinfo *finfo = ((ZIPfileinfo *) (handle->opaque));
@@ -1233,15 +1246,18 @@
 } /* ZIP_exists */
 
 
-static PHYSFS_sint64 ZIP_getLastModTime(DirHandle *h, const char *name)
+static PHYSFS_sint64 ZIP_getLastModTime(DirHandle *h,
+                                        const char *name,
+                                        int *fileExists)
 {
     ZIPentry *entry = zip_find_entry((ZIPinfo *) h->opaque, name);
+    *fileExists = (entry != NULL);
     BAIL_IF_MACRO(entry == NULL, NULL, -1);
     return(entry->last_mod_time);
 } /* ZIP_getLastModTime */
 
 
-static int ZIP_isDirectory(DirHandle *h, const char *name)
+static int ZIP_isDirectory(DirHandle *h, const char *name, int *fileExists)
 {
     ZIPinfo *info = (ZIPinfo *) h->opaque;
     PHYSFS_uint32 pos;
@@ -1249,10 +1265,14 @@
 
     pos = zip_find_start_of_dir(info, name, 1);
     if (pos >= 0)
+    {
+        *fileExists = 1;
         return(1); /* definitely a dir. */
+    } /* if */
 
     /* Follow symlinks. This means we might need to resolve entries. */
     entry = zip_find_entry(info, name);
+    *fileExists = (entry != NULL);
     BAIL_IF_MACRO(entry == NULL, ERR_NO_SUCH_FILE, 0);
 
     if (entry->resolved == ZIP_UNRESOLVED_SYMLINK) /* gotta resolve it. */
@@ -1273,9 +1293,10 @@
 } /* ZIP_isDirectory */
 
 
-static int ZIP_isSymLink(DirHandle *h, const char *name)
+static int ZIP_isSymLink(DirHandle *h, const char *name, int *fileExists)
 {
     ZIPentry *entry = zip_find_entry((ZIPinfo *) h->opaque, name);
+    *fileExists = (entry != NULL);
     BAIL_IF_MACRO(entry == NULL, NULL, 0);
     return(zip_entry_is_symlink(entry));
 } /* ZIP_isSymLink */
@@ -1305,14 +1326,15 @@
 } /* zip_get_file_handle */
 
 
-static FileHandle *ZIP_openRead(DirHandle *h, const char *filename)
+static FileHandle *ZIP_openRead(DirHandle *h, const char *fnm, int *fileExists)
 {
     ZIPinfo *info = (ZIPinfo *) h->opaque;
-    ZIPentry *entry = zip_find_entry(info, filename);
+    ZIPentry *entry = zip_find_entry(info, fnm);
     FileHandle *retval = NULL;
     ZIPfileinfo *finfo = NULL;
     void *in;
 
+    *fileExists = (entry != NULL);
     BAIL_IF_MACRO(entry == NULL, NULL, NULL);
 
     in = zip_get_file_handle(info->archiveName, info, entry);
@@ -1354,6 +1376,18 @@
 } /* ZIP_openRead */
 
 
+static FileHandle *ZIP_openWrite(DirHandle *h, const char *filename)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* ZIP_openWrite */
+
+
+static FileHandle *ZIP_openAppend(DirHandle *h, const char *filename)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* ZIP_openAppend */
+
+
 static void ZIP_dirClose(DirHandle *h)
 {
     ZIPinfo *zi = (ZIPinfo *) (h->opaque);
@@ -1363,6 +1397,18 @@
     free(h);
 } /* ZIP_dirClose */
 
+
+static int ZIP_remove(DirHandle *h, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
+} /* ZIP_remove */
+
+
+static int ZIP_mkdir(DirHandle *h, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
+} /* ZIP_mkdir */
+
 #endif  /* defined PHYSFS_SUPPORTS_ZIP */
 
 /* end of zip.c ... */
--- a/physfs.c	Wed Aug 21 02:58:30 2002 +0000
+++ b/physfs.c	Wed Aug 21 02:59:15 2002 +0000
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <fcntl.h>
 #include <errno.h>
-#include <assert.h>
 #include "physfs.h"
 
 #define __PHYSICSFS_INTERNAL__
@@ -70,7 +69,6 @@
 extern const DirFunctions  __PHYSFS_DirFunctions_DIR;
 
 
-// !!! FIXME: This is stored with dirFunctions now, too.
 static const PHYSFS_ArchiveInfo *supported_types[] =
 {
 #if (defined PHYSFS_SUPPORTS_ZIP)
@@ -1198,10 +1196,12 @@
 int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
 {
     int retval = 1;
+    int fileExists;
     char *start;
     char *end;
     char *str;
 
+    /* !!! FIXME: Can we ditch this malloc()? */
     start = str = malloc(strlen(fname) + 1);
     BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
     strcpy(str, fname);
@@ -1222,11 +1222,16 @@
             break;
         } /* if */
 
-        if ((!allowSymLinks) && (h->funcs->isSymLink(h, str)))
+        if (!allowSymLinks)
         {
-            __PHYSFS_setError(ERR_SYMLINK_DISALLOWED);
-            retval = 0;
-            break;
+            if (h->funcs->isSymLink(h, str, &fileExists))
+            {
+                __PHYSFS_setError(ERR_SYMLINK_DISALLOWED);
+                retval = 0;
+                break;
+            } /* if */
+
+            /* !!! FIXME: Abort early here if !fileExists? */
         } /* if */
 
         if (end == NULL)
@@ -1256,7 +1261,6 @@
     __PHYSFS_platformGrabMutex(stateLock);
     BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
     h = writeDir->dirHandle;
-    BAIL_IF_MACRO_MUTEX(!h->funcs->mkdir, ERR_NOT_SUPPORTED, stateLock, 0);
     BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, dname), NULL, stateLock, 0);
     start = str = malloc(strlen(dname) + 1);
     BAIL_IF_MACRO_MUTEX(str == NULL, ERR_OUT_OF_MEMORY, stateLock, 0);
@@ -1299,7 +1303,6 @@
 
     BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
     h = writeDir->dirHandle;
-    BAIL_IF_MACRO_MUTEX(!h->funcs->remove, ERR_NOT_SUPPORTED, stateLock, 0);
     BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname), NULL, stateLock, 0);
     retval = h->funcs->remove(h, fname);
 
@@ -1311,28 +1314,24 @@
 const char *PHYSFS_getRealDir(const char *filename)
 {
     PhysDirInfo *i;
+    const char *retval = NULL;
 
     while (*filename == '/')
         filename++;
 
     __PHYSFS_platformGrabMutex(stateLock);
-    for (i = searchPath; i != NULL; i = i->next)
+    for (i = searchPath; ((i != NULL) && (retval == NULL)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
         if (__PHYSFS_verifySecurity(h, filename))
         {
-            if (!h->funcs->exists(h, filename))
-                __PHYSFS_setError(ERR_NO_SUCH_FILE);
-            else
-            {
-                __PHYSFS_platformReleaseMutex(stateLock);
-                return(i->dirName);
-            } /* else */
+            if (h->funcs->exists(h, filename))
+                retval = i->dirName;
         } /* if */
     } /* for */
     __PHYSFS_platformReleaseMutex(stateLock);
 
-    return(NULL);
+    return(retval);
 } /* PHYSFS_getRealDir */
 
 
@@ -1467,6 +1466,8 @@
 PHYSFS_sint64 PHYSFS_getLastModTime(const char *fname)
 {
     PhysDirInfo *i;
+    PHYSFS_sint64 retval = -1;
+    int fileExists = 0;
 
     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
     while (*fname == '/')
@@ -1476,95 +1477,67 @@
         return(1);
 
     __PHYSFS_platformGrabMutex(stateLock);
-    for (i = searchPath; i != NULL; i = i->next)
+    for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
         if (__PHYSFS_verifySecurity(h, fname))
-        {
-            if (!h->funcs->exists(h, fname))
-                __PHYSFS_setError(ERR_NO_SUCH_FILE);
-            else
-            {
-                PHYSFS_sint64 retval = -1;
-                if (h->funcs->getLastModTime == NULL)
-                    __PHYSFS_setError(ERR_NOT_SUPPORTED);
-                else
-                    retval = h->funcs->getLastModTime(h, fname);
-
-                __PHYSFS_platformReleaseMutex(stateLock);
-                return(retval);
-            } /* else */
-        } /* if */
+            retval = h->funcs->getLastModTime(h, fname, &fileExists);
     } /* for */
     __PHYSFS_platformReleaseMutex(stateLock);
 
-    return(-1);  /* error set in verifysecurity/exists */
+    return(retval);
 } /* PHYSFS_getLastModTime */
 
 
 int PHYSFS_isDirectory(const char *fname)
 {
     PhysDirInfo *i;
+    int retval = 0;
+    int fileExists = 0;
 
     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
     while (*fname == '/')
         fname++;
 
-    if (*fname == '\0')
-        return(1);
+    BAIL_IF_MACRO(*fname == '\0', NULL, 1); /* Root is always a dir.  :) */
 
     __PHYSFS_platformGrabMutex(stateLock);
-    for (i = searchPath; i != NULL; i = i->next)
+    for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
         if (__PHYSFS_verifySecurity(h, fname))
-        {
-            if (!h->funcs->exists(h, fname))
-                __PHYSFS_setError(ERR_NO_SUCH_FILE);
-            else
-            {
-                int retval = h->funcs->isDirectory(h, fname);
-                __PHYSFS_platformReleaseMutex(stateLock);
-                return(retval);
-            } /* else */
-        } /* if */
+            retval = h->funcs->isDirectory(h, fname, &fileExists);
     } /* for */
     __PHYSFS_platformReleaseMutex(stateLock);
 
-    return(0);
+    return(retval);
 } /* PHYSFS_isDirectory */
 
 
 int PHYSFS_isSymbolicLink(const char *fname)
 {
     PhysDirInfo *i;
+    int retval = 0;
+    int fileExists = 0;
 
-    if (!allowSymLinks)
-        return(0);
+    BAIL_IF_MACRO(!allowSymLinks, ERR_SYMLINK_DISALLOWED, 0);
 
     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
     while (*fname == '/')
         fname++;
 
+    BAIL_IF_MACRO(*fname == '\0', NULL, 0);   /* Root is never a symlink */
+
     __PHYSFS_platformGrabMutex(stateLock);
-    for (i = searchPath; i != NULL; i = i->next)
+    for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
         if (__PHYSFS_verifySecurity(h, fname))
-        {
-            if (!h->funcs->exists(h, fname))
-                __PHYSFS_setError(ERR_NO_SUCH_FILE);
-            else
-            {
-                int retval = h->funcs->isSymLink(h, fname);
-                __PHYSFS_platformReleaseMutex(stateLock);
-                return(retval);
-            } /* else */
-        } /* if */
+            retval = h->funcs->isSymLink(h, fname, &fileExists);
     } /* for */
     __PHYSFS_platformReleaseMutex(stateLock);
 
-    return(0);
+    return(retval);
 } /* PHYSFS_isSymbolicLink */
 
 
@@ -1620,9 +1593,10 @@
 
 PHYSFS_file *PHYSFS_openRead(const char *fname)
 {
-    PHYSFS_file *retval;
+    PHYSFS_file *retval = NULL;
     FileHandle *rc = NULL;
     FileHandleList *list;
+    int fileExists = 0;
     PhysDirInfo *i;
 
     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL);
@@ -1631,17 +1605,12 @@
 
     __PHYSFS_platformGrabMutex(stateLock);
     BAIL_IF_MACRO_MUTEX(!searchPath, ERR_NOT_IN_SEARCH_PATH, stateLock, NULL);
-    for (i = searchPath; i != NULL; i = i->next)
+    for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
         if (__PHYSFS_verifySecurity(h, fname))
-        {
-            rc = h->funcs->openRead(h, fname);
-            if (rc != NULL)
-                break;
-        } /* if */
+            rc = h->funcs->openRead(h, fname, &fileExists);
     } /* for */
-
     BAIL_IF_MACRO_MUTEX(rc == NULL, NULL, stateLock, NULL);
 
     list = (FileHandleList *) malloc(sizeof (FileHandleList));
@@ -1711,9 +1680,6 @@
                           PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
-    assert(h != NULL);
-    assert(h->funcs != NULL);
-    BAIL_IF_MACRO(h->funcs->read == NULL, ERR_NOT_SUPPORTED, -1);
     return(h->funcs->read(h, buffer, objSize, objCount));
 } /* PHYSFS_read */
 
@@ -1722,9 +1688,6 @@
                            PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
-    assert(h != NULL);
-    assert(h->funcs != NULL);
-    BAIL_IF_MACRO(h->funcs->write == NULL, ERR_NOT_SUPPORTED, -1);
     return(h->funcs->write(h, buffer, objSize, objCount));
 } /* PHYSFS_write */
 
@@ -1732,9 +1695,6 @@
 int PHYSFS_eof(PHYSFS_file *handle)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
-    assert(h != NULL);
-    assert(h->funcs != NULL);
-    BAIL_IF_MACRO(h->funcs->eof == NULL, ERR_NOT_SUPPORTED, -1);
     return(h->funcs->eof(h));
 } /* PHYSFS_eof */
 
@@ -1742,9 +1702,6 @@
 PHYSFS_sint64 PHYSFS_tell(PHYSFS_file *handle)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
-    assert(h != NULL);
-    assert(h->funcs != NULL);
-    BAIL_IF_MACRO(h->funcs->tell == NULL, ERR_NOT_SUPPORTED, -1);
     return(h->funcs->tell(h));
 } /* PHYSFS_tell */
 
@@ -1752,10 +1709,6 @@
 int PHYSFS_seek(PHYSFS_file *handle, PHYSFS_uint64 pos)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
-    assert(h != NULL);
-    assert(h->funcs != NULL);
-    BAIL_IF_MACRO(h->funcs->seek == NULL, ERR_NOT_SUPPORTED, 0);
-    BAIL_IF_MACRO(pos < 0, ERR_INVALID_ARGUMENT, 0);
     return(h->funcs->seek(h, pos));
 } /* PHYSFS_seek */
 
@@ -1763,10 +1716,6 @@
 PHYSFS_sint64 PHYSFS_fileLength(PHYSFS_file *handle)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
-    assert(h != NULL);
-    assert(h->funcs != NULL);
-    BAIL_IF_MACRO(h->funcs->fileLength == NULL, ERR_NOT_SUPPORTED, 0);
-
     return(h->funcs->fileLength(h));
 } /* PHYSFS_filelength */
 
--- a/physfs_internal.h	Wed Aug 21 02:58:30 2002 +0000
+++ b/physfs_internal.h	Wed Aug 21 02:59:15 2002 +0000
@@ -842,6 +842,7 @@
         /*
          * Returns non-zero if filename can be opened for reading.
          *  This filename is in platform-independent notation.
+         *  You should not follow symlinks.
          */
     int (*exists)(DirHandle *r, const char *name);
 
@@ -850,22 +851,34 @@
          *  This filename is in platform-independent notation.
          *  Symlinks should be followed; if what the symlink points
          *  to is missing, or isn't a directory, then the retval is zero.
+         *
+         * Regardless of success or failure, please set *fileExists to
+         *  non-zero if the file existed (even if it's a broken symlink!),
+         *  zero if it did not.
          */
-    int (*isDirectory)(DirHandle *r, const char *name);
+    int (*isDirectory)(DirHandle *r, const char *name, int *fileExists);
 
         /*
          * Returns non-zero if filename is really a symlink.
          *  This filename is in platform-independent notation.
+         *
+         * Regardless of success or failure, please set *fileExists to
+         *  non-zero if the file existed (even if it's a broken symlink!),
+         *  zero if it did not.
          */
-    int (*isSymLink)(DirHandle *r, const char *name);
+    int (*isSymLink)(DirHandle *r, const char *name, int *fileExists);
 
         /*
 	     * Retrieve the last modification time (mtime) of a file.
     	 *  Returns -1 on failure, or the file's mtime in seconds since
     	 *  the epoch (Jan 1, 1970) on success.
          *  This filename is in platform-independent notation.
+         *
+         * Regardless of success or failure, please set *exists to
+         *  non-zero if the file existed (even if it's a broken symlink!),
+         *  zero if it did not.
     	 */
-    PHYSFS_sint64 (*getLastModTime)(DirHandle *r, const char *filename);
+    PHYSFS_sint64 (*getLastModTime)(DirHandle *r, const char *fnm, int *exist);
 
         /*
          * Open file for reading, and return a FileHandle.
@@ -874,8 +887,12 @@
          *  you can opt to fail for the second call.
          * Fail if the file does not exist.
          * Returns NULL on failure, and calls __PHYSFS_setError().
+         *
+         * Regardless of success or failure, please set *fileExists to
+         *  non-zero if the file existed (even if it's a broken symlink!),
+         *  zero if it did not.
          */
-    FileHandle *(*openRead)(DirHandle *r, const char *filename);
+    FileHandle *(*openRead)(DirHandle *r, const char *fname, int *fileExists);
 
         /*
          * Open file for writing, and return a FileHandle.
@@ -1245,8 +1262,10 @@
 
 /*
  * Return non-zero if filename (in platform-dependent notation) exists.
- *  Symlinks should be followed; if what the symlink points to is missing,
- *  then the retval is false.
+ *  Symlinks should NOT be followed; at this stage, we do not care what the
+ *  symlink points to. Please call __PHYSFS_SetError() with the details of
+ *  why the file does not exist, if it doesn't; you are in a better position
+ *  to know (path not found, bogus filename, file itself is missing, etc).
  */
 int __PHYSFS_platformExists(const char *fname);
 
@@ -1258,7 +1277,6 @@
  */
 PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname);
 
-
 /*
  * Return non-zero if filename (in platform-dependent notation) is a symlink.
  */
--- a/platform/posix.c	Wed Aug 21 02:58:30 2002 +0000
+++ b/platform/posix.c	Wed Aug 21 02:59:15 2002 +0000
@@ -144,10 +144,17 @@
 } /* __PHYSFS_platformStricmp */
 
 
+#if (defined __PHYSFS_NO_SYMLINKS__)
+#define doStat stat
+#else
+#define doStat lstat
+#endif
+
 int __PHYSFS_platformExists(const char *fname)
 {
     struct stat statbuf;
-    return(stat(fname, &statbuf) == 0);
+    BAIL_IF_MACRO(doStat(fname, &statbuf) == -1, strerror(errno), 0);
+    return(1);
 } /* __PHYSFS_platformExists */
 
 
@@ -156,18 +163,9 @@
 #if (defined __PHYSFS_NO_SYMLINKS__)
     return(0);
 #else
-
     struct stat statbuf;
-    int retval = 0;
-
-    if (lstat(fname, &statbuf) == 0)
-    {
-        if (S_ISLNK(statbuf.st_mode))
-            retval = 1;
-    } /* if */
-    
-    return(retval);
-
+    BAIL_IF_MACRO(lstat(fname, &statbuf) == -1, strerror(errno), 0);
+    return( (S_ISLNK(statbuf.st_mode)) ? 1 : 0 );
 #endif
 } /* __PHYSFS_platformIsSymlink */
 
@@ -175,15 +173,8 @@
 int __PHYSFS_platformIsDirectory(const char *fname)
 {
     struct stat statbuf;
-    int retval = 0;
-
-    if (stat(fname, &statbuf) == 0)
-    {
-        if (S_ISDIR(statbuf.st_mode))
-            retval = 1;
-    } /* if */
-    
-    return(retval);
+    BAIL_IF_MACRO(stat(fname, &statbuf) == -1, strerror(errno), 0);
+    return( (S_ISDIR(statbuf.st_mode)) ? 1 : 0 );
 } /* __PHYSFS_platformIsDirectory */
 
 
--- a/platform/win32.c	Wed Aug 21 02:58:30 2002 +0000
+++ b/platform/win32.c	Wed Aug 21 02:59:15 2002 +0000
@@ -369,7 +369,9 @@
 
 int __PHYSFS_platformExists(const char *fname)
 {
-    return(GetFileAttributes(fname) != INVALID_FILE_ATTRIBUTES);
+    BAIL_IF_MACRO(GetFileAttributes(fname) == INVALID_FILE_ATTRIBUTES,
+                  win32strerror(), 0);
+    return(1);
 } /* __PHYSFS_platformExists */