Added typedefs and platform-specific i/o.
authorRyan C. Gordon <icculus@icculus.org>
Sun, 24 Mar 2002 19:47:33 +0000
changeset 132 b53fa5093749
parent 131 69b093825303
child 133 293f14af15c8
Added typedefs and platform-specific i/o.
CHANGELOG
Makefile
archivers/dir.c
archivers/grp.c
archivers/zip.c
extras/physfsrwops.c
extras/physfsrwops.h
physfs.c
physfs.h
physfs_internal.h
platform/unix.c
test/test_physfs.c
--- a/CHANGELOG	Sun Mar 24 19:42:21 2002 +0000
+++ b/CHANGELOG	Sun Mar 24 19:47:33 2002 +0000
@@ -70,7 +70,11 @@
            "write" functions to get data from a "const" buffer. Added an
            "extras" dir, which currently contains PhysFS->SDL_RWops glue code.
 03202002 - Patched platform/win32.c to compile.
-03242002 - Added __PHYSFS_platformInit() and __PHYSFS_platformDeinit().
+03242002 - Added __PHYSFS_platformInit() and __PHYSFS_platformDeinit(). Win32
+           improvements by Gregory S. Read. Added PHYSFS_[us]int(8|16|32)
+           types...this breaks binary compatibility with previous PhysicsFS
+           releases! Added platform specific i/o functions, so we don't have
+           to rely on stdio anymore.
 
 --ryan. (icculus@clutteredmind.org)
 
--- a/Makefile	Sun Mar 24 19:42:21 2002 +0000
+++ b/Makefile	Sun Mar 24 19:47:33 2002 +0000
@@ -136,7 +136,8 @@
 SRCDIR := .
 
 CFLAGS += $(use_asm) -I$(SRCDIR) -I/usr/include/readline -D_REENTRANT -fsigned-char -DPLATFORM_UNIX
-CFLAGS += -Wall -Werror -fno-exceptions -fno-rtti -ansi -pedantic
+CFLAGS += -Wall -Werror -fno-exceptions -fno-rtti -ansi
+#-pedantic
 
 LDFLAGS += -lm
 
--- a/archivers/dir.c	Sun Mar 24 19:42:21 2002 +0000
+++ b/archivers/dir.c	Sun Mar 24 19:47:33 2002 +0000
@@ -16,14 +16,14 @@
 #define __PHYSICSFS_INTERNAL__
 #include "physfs_internal.h"
 
-static int DIR_read(FileHandle *handle, void *buffer,
-                    unsigned int objSize, unsigned int objCount);
-static int DIR_write(FileHandle *handle, const void *buffer,
-                     unsigned int objSize, unsigned int objCount);
+static PHYSFS_sint64 DIR_read(FileHandle *handle, void *buffer,
+                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+static PHYSFS_sint64 DIR_write(FileHandle *handle, const void *buffer,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 static int DIR_eof(FileHandle *handle);
-static int DIR_tell(FileHandle *handle);
-static int DIR_seek(FileHandle *handle, int offset);
-static int DIR_fileLength(FileHandle *handle);
+static PHYSFS_sint64 DIR_tell(FileHandle *handle);
+static int DIR_seek(FileHandle *handle, PHYSFS_uint64 offset);
+static PHYSFS_sint64 DIR_fileLength(FileHandle *handle);
 static int DIR_fileClose(FileHandle *handle);
 static int DIR_isArchive(const char *filename, int forWriting);
 static DirHandle *DIR_openArchive(const char *name, int forWriting);
@@ -94,8 +94,8 @@
 #endif
 
 
-static int DIR_read(FileHandle *handle, void *buffer,
-                    unsigned int objSize, unsigned int objCount)
+static PHYSFS_sint64 DIR_read(FileHandle *handle, void *buffer,
+                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
 {
     FILE *h = (FILE *) (handle->opaque);
     size_t retval;
@@ -109,8 +109,8 @@
 } /* DIR_read */
 
 
-static int DIR_write(FileHandle *handle, const void *buffer,
-                     unsigned int objSize, unsigned int objCount)
+static PHYSFS_sint64 DIR_write(FileHandle *handle, const void *buffer,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
 {
     FILE *h = (FILE *) (handle->opaque);
     size_t retval;
@@ -130,19 +130,19 @@
 } /* DIR_eof */
 
 
-static int DIR_tell(FileHandle *handle)
+static PHYSFS_sint64 DIR_tell(FileHandle *handle)
 {
     return(ftell((FILE *) (handle->opaque)));
 } /* DIR_tell */
 
 
-static int DIR_seek(FileHandle *handle, int offset)
+static int DIR_seek(FileHandle *handle, PHYSFS_uint64 offset)
 {
     return(fseek((FILE *) (handle->opaque), offset, SEEK_SET) == 0);
 } /* DIR_seek */
 
 
-static int DIR_fileLength(FileHandle *handle)
+static PHYSFS_sint64 DIR_fileLength(FileHandle *handle)
 {
     return(__PHYSFS_platformFileLength((FILE *) (handle->opaque)));
 } /* DIR_fileLength */
--- a/archivers/grp.c	Sun Mar 24 19:42:21 2002 +0000
+++ b/archivers/grp.c	Sun Mar 24 19:47:33 2002 +0000
@@ -39,35 +39,33 @@
 #define __PHYSICSFS_INTERNAL__
 #include "physfs_internal.h"
 
-#if 0
 #if (!defined PHYSFS_SUPPORTS_GRP)
 #error PHYSFS_SUPPORTS_GRP must be defined.
 #endif
-#endif
 
 /* !!! FIXME: Using the same file handle for all reads is a RACE CONDITION! */
 
 typedef struct
 {
     FILE *handle;
-    int totalEntries;
+    PHYSFS_uint32 totalEntries;
 } GRPinfo;
 
 typedef struct
 {
-    int startPos;
-    int curPos;
-    int size;
+    PHYSFS_uint32 startPos;
+    PHYSFS_uint32 curPos;
+    PHYSFS_uint32 size;
 } GRPfileinfo;
 
 
 static void GRP_dirClose(DirHandle *h);
-static int GRP_read(FileHandle *handle, void *buffer,
-                    unsigned int objSize, unsigned int objCount);
+static PHYSFS_sint64 GRP_read(FileHandle *handle, void *buffer,
+                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 static int GRP_eof(FileHandle *handle);
-static int GRP_tell(FileHandle *handle);
-static int GRP_seek(FileHandle *handle, int offset);
-static int GRP_fileLength(FileHandle *handle);
+static PHYSFS_sint64 GRP_tell(FileHandle *handle);
+static int GRP_seek(FileHandle *handle, PHYSFS_uint64 offset);
+static PHYSFS_sint64 GRP_fileLength(FileHandle *handle);
 static int GRP_fileClose(FileHandle *handle);
 static int GRP_isArchive(const char *filename, int forWriting);
 static DirHandle *GRP_openArchive(const char *name, int forWriting);
@@ -125,13 +123,13 @@
 } /* GRP_dirClose */
 
 
-static int GRP_read(FileHandle *handle, void *buffer,
-                    unsigned int objSize, unsigned int objCount)
+static PHYSFS_sint64 GRP_read(FileHandle *handle, void *buffer,
+                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
 {
     GRPfileinfo *finfo = (GRPfileinfo *) (handle->opaque);
     FILE *fh = (FILE *) (((GRPinfo *) (handle->dirHandle->opaque))->handle);
-    int bytesLeft = (finfo->startPos + finfo->size) - finfo->curPos;
-    unsigned int objsLeft = bytesLeft / objSize;
+    PHYSFS_uint32 bytesLeft = (finfo->startPos + finfo->size) - finfo->curPos;
+    PHYSFS_uint32 objsLeft = bytesLeft / objSize;
     size_t retval = 0;
 
     if (objsLeft < objCount)
@@ -144,9 +142,9 @@
     retval = fread(buffer, objSize, objCount, fh);
     finfo->curPos += (retval * objSize);
     BAIL_IF_MACRO((retval < (size_t) objCount) && (ferror(fh)),
-                   strerror(errno), (int) retval);
+                   strerror(errno), (PHYSFS_sint64) retval);
 
-    return((int) retval);
+    return((PHYSFS_sint64) retval);
 } /* GRP_read */
 
 
@@ -157,14 +155,14 @@
 } /* GRP_eof */
 
 
-static int GRP_tell(FileHandle *handle)
+static PHYSFS_sint64 GRP_tell(FileHandle *handle)
 {
     GRPfileinfo *finfo = (GRPfileinfo *) (handle->opaque);
     return(finfo->curPos - finfo->startPos);
 } /* GRP_tell */
 
 
-static int GRP_seek(FileHandle *handle, int offset)
+static int GRP_seek(FileHandle *handle, PHYSFS_uint64 offset)
 {
     GRPfileinfo *finfo = (GRPfileinfo *) (handle->opaque);
     int newPos = finfo->startPos + offset;
@@ -176,7 +174,7 @@
 } /* GRP_seek */
 
 
-static int GRP_fileLength(FileHandle *handle)
+static PHYSFS_sint64 GRP_fileLength(FileHandle *handle)
 {
     GRPfileinfo *finfo = (GRPfileinfo *) (handle->opaque);
     return(finfo->size);
@@ -191,14 +189,10 @@
 } /* GRP_fileClose */
 
 
-static int openGrp(const char *filename, int forWriting, FILE **fh, int *count)
+static int openGrp(const char *filename, int forWriting, FILE **fh, PHYSFS_sint32 *count)
 {
     char buf[12];
 
-     /* !!! FIXME: Get me platform-independent typedefs! */
-    if (sizeof (int) != 4)
-        assert(0);
-
     *fh = NULL;
     BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
 
@@ -208,10 +202,10 @@
     
     errno = 0;
     BAIL_IF_MACRO(fread(buf, 12, 1, *fh) != 1, strerror(errno), 0);
-    BAIL_IF_MACRO(strncmp(buf, "KenSilverman", 12) != 0,
+    BAIL_IF_MACRO(memcmp(buf, "KenSilverman", 12) != 0,
                     ERR_UNSUPPORTED_ARCHIVE, 0);
 
-    if (fread(count, 4, 1, *fh) != 1)
+    if (fread(count, sizeof (PHYSFS_sint32), 1, *fh) != 1)
         *count = 0;
 
     return(1);
@@ -312,7 +306,8 @@
 } /* GRP_enumerateFiles */
 
 
-static int getFileEntry(DirHandle *h, const char *name, int *size)
+static PHYSFS_sint32 getFileEntry(DirHandle *h, const char *name,
+                                  PHYSFS_sint32 *size)
 {
     char buf[16];
     GRPinfo *g = (GRPinfo *) (h->opaque);
@@ -338,23 +333,24 @@
 
     for (i = 0; i < g->totalEntries; i++)
     {
-        int fsize;
+        PHYSFS_sint32 l = 0;
 
         errno = 0;
-        BAIL_IF_MACRO(fread(buf, 16, 1, fh) != 1, strerror(errno), -1);
+        BAIL_IF_MACRO(fread(buf, 12, 1, fh) != 1, strerror(errno), -1);
 
-        fsize = *((int *) (buf + 12));
+        errno = 0;
+        BAIL_IF_MACRO(fread(&l, sizeof (l), 1, fh) != 1, strerror(errno), -1);
 
         buf[12] = '\0';  /* FILENAME.EXT is all you get. */
 
         if (__PHYSFS_platformStricmp(buf, name) == 0)
         {
             if (size != NULL)
-                *size = fsize;
+                *size = l;
             return(retval);
         } /* if */
 
-        retval += fsize;
+        retval += l;
     } /* for */
 
     return(-1);  /* not found. */
@@ -383,7 +379,8 @@
 {
     FileHandle *retval;
     GRPfileinfo *finfo;
-    int size, offset;
+    PHYSFS_sint32 size;
+    PHYSFS_sint32 offset;
 
     offset = getFileEntry(h, name, &size);
     BAIL_IF_MACRO(offset == -1, ERR_NO_SUCH_FILE, NULL);
--- a/archivers/zip.c	Sun Mar 24 19:42:21 2002 +0000
+++ b/archivers/zip.c	Sun Mar 24 19:47:33 2002 +0000
@@ -58,12 +58,12 @@
 #define SYMLINK_RECURSE_COUNT 20
 
 
-static int ZIP_read(FileHandle *handle, void *buffer,
-                    unsigned int objSize, unsigned int objCount);
+static PHYSFS_sint64 ZIP_read(FileHandle *handle, void *buffer,
+                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 static int ZIP_eof(FileHandle *handle);
-static int ZIP_tell(FileHandle *handle);
-static int ZIP_seek(FileHandle *handle, int offset);
-static int ZIP_fileLength(FileHandle *handle);
+static PHYSFS_sint64 ZIP_tell(FileHandle *handle);
+static int ZIP_seek(FileHandle *handle, PHYSFS_uint64 offset);
+static PHYSFS_sint64 ZIP_fileLength(FileHandle *handle);
 static int ZIP_fileClose(FileHandle *handle);
 static int ZIP_isArchive(const char *filename, int forWriting);
 static char *ZIP_realpath(unzFile fh, unz_file_info *info);
@@ -116,12 +116,12 @@
 
 
 
-static int ZIP_read(FileHandle *handle, void *buffer,
-                    unsigned int objSize, unsigned int objCount)
+static PHYSFS_sint64 ZIP_read(FileHandle *handle, void *buffer,
+                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
 {
     unzFile fh = ((ZIPfileinfo *) (handle->opaque))->handle;
-    int bytes = objSize * objCount;
-    int rc = unzReadCurrentFile(fh, buffer, bytes);
+    int bytes = (int) (objSize * objCount); /* !!! FIXME: overflow? */
+    PHYSFS_sint32 rc = unzReadCurrentFile(fh, buffer, bytes);
 
     if (rc < bytes)
         __PHYSFS_setError(ERR_PAST_EOF);
@@ -140,18 +140,18 @@
 } /* ZIP_eof */
 
 
-static int ZIP_tell(FileHandle *handle)
+static PHYSFS_sint64 ZIP_tell(FileHandle *handle)
 {
     return(unztell(((ZIPfileinfo *) (handle->opaque))->handle));
 } /* ZIP_tell */
 
 
-static int ZIP_seek(FileHandle *handle, int offset)
+static int ZIP_seek(FileHandle *handle, PHYSFS_uint64 offset)
 {
-    /* this blows. */
+    /* !!! FIXME : this blows. */
     unzFile fh = ((ZIPfileinfo *) (handle->opaque))->handle;
     char *buf = NULL;
-    int bufsize = 4096 * 2;
+    PHYSFS_uint32 bufsize = 4096 * 2;
 
     BAIL_IF_MACRO(unztell(fh) == offset, NULL, 1);
     BAIL_IF_MACRO(ZIP_fileLength(handle) <= offset, ERR_PAST_EOF, 0);
@@ -169,8 +169,8 @@
 
     while (offset > 0)
     {
-        int chunk = (offset > bufsize) ? bufsize : offset;
-        int rc = unzReadCurrentFile(fh, buf, chunk);
+        PHYSFS_uint32 chunk = (offset > bufsize) ? bufsize : offset;
+        PHYSFS_sint32 rc = unzReadCurrentFile(fh, buf, chunk);
         BAIL_IF_MACRO(rc == 0, ERR_IO_ERROR, 0);  /* shouldn't happen. */
         BAIL_IF_MACRO(rc == UNZ_ERRNO, ERR_IO_ERROR, 0);
         BAIL_IF_MACRO(rc < 0, ERR_COMPRESSION, 0);
@@ -182,7 +182,7 @@
 } /* ZIP_seek */
 
 
-static int ZIP_fileLength(FileHandle *handle)
+static PHYSFS_sint64 ZIP_fileLength(FileHandle *handle)
 {
     ZIPfileinfo *finfo = (ZIPfileinfo *) (handle->opaque);
     unz_file_info info;
--- a/extras/physfsrwops.c	Sun Mar 24 19:42:21 2002 +0000
+++ b/extras/physfsrwops.c	Sun Mar 24 19:47:33 2002 +0000
@@ -34,7 +34,7 @@
 
     else if (whence == SEEK_CUR)
     {
-        int current = PHYSFS_tell(handle);
+        PHYSFS_sint64 current = PHYSFS_tell(handle);
         if (current == -1)
         {
             SDL_SetError("Can't find position in file: %s",
@@ -42,22 +42,36 @@
             return(-1);
         } /* if */
 
+        pos = (int) current;
+        if ( ((PHYSFS_sint64) pos) != current )
+        {
+            SDL_SetError("Can't fit current file position in an int!");
+            return(-1);
+        } /* if */
+
         if (offset == 0)  /* this is a "tell" call. We're done. */
-            return(offset);
+            return(pos);
 
-        pos = current + offset;
+        pos += offset;
     } /* else if */
 
     else if (whence == SEEK_END)
     {
-        int len = PHYSFS_fileLength(handle);
+        PHYSFS_sint64 len = PHYSFS_fileLength(handle);
         if (len == -1)
         {
             SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
             return(-1);
         } /* if */
 
-        pos = len + offset;
+        pos = (int) len;
+        if ( ((PHYSFS_sint64) pos) != len )
+        {
+            SDL_SetError("Can't fit end-of-file position in an int!");
+            return(-1);
+        } /* if */
+
+        pos += offset;
     } /* else if */
 
     else
@@ -66,7 +80,13 @@
         return(-1);
     } /* else */
 
-    if (!PHYSFS_seek(handle, pos))
+    if ( pos < 0 )
+    {
+        SDL_SetError("Attempt to seek past start of file.");
+        return(-1);
+    } /* if */
+    
+    if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
     {
         SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
         return(-1);
@@ -79,25 +99,25 @@
 static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
 {
     PHYSFS_file *handle = (PHYSFS_file *) rw->hidden.unknown.data1;
-    int rc = PHYSFS_read(handle, ptr, size, maxnum);
+    PHYSFS_sint64 rc = PHYSFS_read(handle, ptr, size, maxnum);
     if (rc != maxnum)
     {
         if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
             SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
     } /* if */
 
-    return(rc);
+    return((int) rc);
 } /* physfsrwops_read */
 
 
 static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
 {
     PHYSFS_file *handle = (PHYSFS_file *) rw->hidden.unknown.data1;
-    int rc = PHYSFS_write(handle, ptr, size, num);
+    PHYSFS_sint64 rc = PHYSFS_write(handle, ptr, size, num);
     if (rc != num)
         SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
 
-    return(rc);
+    return((int) rc);
 } /* physfsrwops_write */
 
 
--- a/extras/physfsrwops.h	Sun Mar 24 19:42:21 2002 +0000
+++ b/extras/physfsrwops.h	Sun Mar 24 19:47:33 2002 +0000
@@ -29,12 +29,6 @@
 extern "C" {
 #endif
 
-#if (defined _MSC_VER)
-#define __EXPORT__ __declspec(dllexport)
-#else
-#define __EXPORT__
-#endif
-
 /**
  * Open a platform-independent filename for reading, and make it accessible
  *  via an SDL_RWops structure. The file will be closed in PhysicsFS when the
--- a/physfs.c	Sun Mar 24 19:42:21 2002 +0000
+++ b/physfs.c	Sun Mar 24 19:47:33 2002 +0000
@@ -803,7 +803,7 @@
     } /* if */
 
     return(str);
-} /* __PHYSFS_convertToDependentNotation */
+} /* __PHYSFS_convertToDependent */
 
 
 int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
@@ -1231,8 +1231,8 @@
 } /* PHYSFS_close */
 
 
-int PHYSFS_read(PHYSFS_file *handle, void *buffer,
-                unsigned int objSize, unsigned int objCount)
+PHYSFS_sint64 PHYSFS_read(PHYSFS_file *handle, void *buffer,
+                          PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
     assert(h != NULL);
@@ -1242,8 +1242,8 @@
 } /* PHYSFS_read */
 
 
-int PHYSFS_write(PHYSFS_file *handle, const void *buffer,
-                 unsigned int objSize, unsigned int objCount)
+PHYSFS_sint64 PHYSFS_write(PHYSFS_file *handle, const void *buffer,
+                           PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
     assert(h != NULL);
@@ -1263,7 +1263,7 @@
 } /* PHYSFS_eof */
 
 
-int PHYSFS_tell(PHYSFS_file *handle)
+PHYSFS_sint64 PHYSFS_tell(PHYSFS_file *handle)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
     assert(h != NULL);
@@ -1273,7 +1273,7 @@
 } /* PHYSFS_tell */
 
 
-int PHYSFS_seek(PHYSFS_file *handle, int pos)
+int PHYSFS_seek(PHYSFS_file *handle, PHYSFS_uint64 pos)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
     assert(h != NULL);
@@ -1284,7 +1284,7 @@
 } /* PHYSFS_seek */
 
 
-int PHYSFS_fileLength(PHYSFS_file *handle)
+PHYSFS_sint64 PHYSFS_fileLength(PHYSFS_file *handle)
 {
     FileHandle *h = (FileHandle *) handle->opaque;
     assert(h != NULL);
--- a/physfs.h	Sun Mar 24 19:42:21 2002 +0000
+++ b/physfs.h	Sun Mar 24 19:47:33 2002 +0000
@@ -148,6 +148,42 @@
 #endif
 
 
+/* !!! FIXME: This is not universal. */
+typedef unsigned char         PHYSFS_uint8;
+typedef signed char           PHYSFS_sint8;
+typedef unsigned short        PHYSFS_uint16;
+typedef signed short          PHYSFS_sint16;
+typedef unsigned int          PHYSFS_uint32;
+typedef signed int            PHYSFS_sint32;
+
+#ifdef PHYSFS_NO_64BIT_SUPPORT  /* oh well. */
+typedef PHYSFS_uint32         PHYSFS_uint64;
+typedef PHYSFS_sint32         PHYSFS_sint64;
+#else
+typedef unsigned long long    PHYSFS_uint64;
+typedef signed long long      PHYSFS_sint64;
+#endif
+
+/* Make sure the types really have the right sizes */
+#define PHYSFS_COMPILE_TIME_ASSERT(name, x)               \
+       typedef int PHYSFS_dummy_ ## name[(x) * 2 - 1]
+
+PHYSFS_COMPILE_TIME_ASSERT(uint8, sizeof(PHYSFS_uint8) == 1);
+PHYSFS_COMPILE_TIME_ASSERT(sint8, sizeof(PHYSFS_sint8) == 1);
+PHYSFS_COMPILE_TIME_ASSERT(uint16, sizeof(PHYSFS_uint16) == 2);
+PHYSFS_COMPILE_TIME_ASSERT(sint16, sizeof(PHYSFS_sint16) == 2);
+PHYSFS_COMPILE_TIME_ASSERT(uint32, sizeof(PHYSFS_uint32) == 4);
+PHYSFS_COMPILE_TIME_ASSERT(sint32, sizeof(PHYSFS_sint32) == 4);
+
+#ifndef PHYSFS_NO_64BIT_SUPPORT
+PHYSFS_COMPILE_TIME_ASSERT(uint64, sizeof(PHYSFS_uint64) == 8);
+PHYSFS_COMPILE_TIME_ASSERT(sint64, sizeof(PHYSFS_sint64) == 8);
+#endif
+
+#undef PHYSFS_COMPILE_TIME_ASSERT
+
+
+
 typedef struct __PHYSFS_FILE__
 {
     void *opaque;
@@ -166,9 +202,9 @@
 
 typedef struct __PHYSFS_VERSION__
 {
-    int major;
-    int minor;
-    int patch;
+    PHYSFS_uint8 major;
+    PHYSFS_uint8 minor;
+    PHYSFS_uint8 patch;
 } PHYSFS_Version;
 
 #define PHYSFS_VER_MAJOR 0
@@ -758,9 +794,10 @@
  *           the reason this might be < (objCount), as can PHYSFS_eof().
  *            -1 if complete failure.
  */
-__EXPORT__ int PHYSFS_read(PHYSFS_file *handle, void *buffer,
-                           unsigned int objSize, unsigned int objCount);
-
+__EXPORT__ PHYSFS_sint64 PHYSFS_read(PHYSFS_file *handle,
+                                     void *buffer,
+                                     PHYSFS_uint32 objSize,
+                                     PHYSFS_uint32 objCount);
 
 /**
  * Write data to a PhysicsFS filehandle. The file must be opened for writing.
@@ -772,9 +809,10 @@
  *  @return number of objects written. PHYSFS_getLastError() can shed light on
  *           the reason this might be < (objCount). -1 if complete failure.
  */
-__EXPORT__ int PHYSFS_write(PHYSFS_file *handle, const void *buffer,
-                            unsigned int objSize, unsigned int objCount);
-
+__EXPORT__ PHYSFS_sint64 PHYSFS_write(PHYSFS_file *handle,
+                                      const void *buffer,
+                                      PHYSFS_uint32 objSize,
+                                      PHYSFS_uint32 objCount);
 
 /**
  * Determine if the end of file has been reached in a PhysicsFS filehandle.
@@ -792,7 +830,7 @@
  *  @return offset in bytes from start of file. -1 if error occurred.
  *           Specifics of the error can be gleaned from PHYSFS_getLastError().
  */
-__EXPORT__ int PHYSFS_tell(PHYSFS_file *handle);
+__EXPORT__ PHYSFS_sint64 PHYSFS_tell(PHYSFS_file *handle);
 
 
 /**
@@ -805,7 +843,7 @@
  *  @return nonzero on success, zero on error. Specifics of the error can be
  *          gleaned from PHYSFS_getLastError().
  */
-__EXPORT__ int PHYSFS_seek(PHYSFS_file *handle, int pos);
+__EXPORT__ int PHYSFS_seek(PHYSFS_file *handle, PHYSFS_uint64 pos);
 
 
 /**
@@ -819,7 +857,7 @@
  *   @param handle handle returned from PHYSFS_open*().
  *  @return size in bytes of the file. -1 if can't be determined.
  */
-__EXPORT__ int PHYSFS_fileLength(PHYSFS_file *handle);
+__EXPORT__ PHYSFS_sint64 PHYSFS_fileLength(PHYSFS_file *handle);
 
 #ifdef __cplusplus
 }
--- a/physfs_internal.h	Sun Mar 24 19:42:21 2002 +0000
+++ b/physfs_internal.h	Sun Mar 24 19:47:33 2002 +0000
@@ -14,6 +14,12 @@
 #error Do not include this header from your applications.
 #endif
 
+#include "physfs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct __PHYSFS_DIRHANDLE__;
 struct __PHYSFS_FILEFUNCTIONS__;
 
@@ -52,8 +58,8 @@
          *  if complete failure.
          * On failure, call __PHYSFS_setError().
          */
-    int (*read)(FileHandle *handle, void *buffer,
-                unsigned int objSize, unsigned int objCount);
+    PHYSFS_sint64 (*read)(FileHandle *handle, void *buffer,
+                          PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 
         /*
          * Write more to the file. Archives don't have to implement this.
@@ -62,8 +68,8 @@
          *  if complete failure.
          * On failure, call __PHYSFS_setError().
          */
-    int (*write)(FileHandle *handle, const void *buffer,
-                 unsigned int objSize, unsigned int objCount);
+    PHYSFS_sint64 (*write)(FileHandle *handle, const void *buffer,
+                 PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
 
         /*
          * Returns non-zero if at end of file.
@@ -73,21 +79,21 @@
         /*
          * Returns byte offset from start of file.
          */
-    int (*tell)(FileHandle *handle);
+    PHYSFS_sint64 (*tell)(FileHandle *handle);
 
         /*
          * Move read/write pointer to byte offset from start of file.
          *  Returns non-zero on success, zero on error.
          * On failure, call __PHYSFS_setError().
          */
-    int (*seek)(FileHandle *handle, int offset);
+    int (*seek)(FileHandle *handle, PHYSFS_uint64 offset);
 
         /*
          * Return number of bytes available in the file, or -1 if you
          *  aren't able to determine.
          * On failure, call __PHYSFS_setError().
          */
-    int (*fileLength)(FileHandle *handle);
+    PHYSFS_sint64 (*fileLength)(FileHandle *handle);
 
         /*
          * Close the file, and free the FileHandle structure (including "opaque").
@@ -341,6 +347,148 @@
 int __PHYSFS_platformDeinit(void);
 
 /*
+ * Open a file for reading. (filename) is in platform-dependent notation. The
+ *  file pointer should be positioned on the first byte of the file.
+ *
+ * The return value will be some platform-specific datatype that is opaque to
+ *  the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32.
+ *
+ * The same file can be opened for read multiple times, and each should have
+ *  a unique file handle; this is frequently employed to prevent race
+ *  conditions in the archivers.
+ *
+ * Call __PHYSFS_setError() and return (NULL) if the file can't be opened.
+ */
+void *__PHYSFS_platformOpenRead(const char *filename);
+
+/*
+ * Open a file for writing. (filename) is in platform-dependent notation. If
+ *  the file exists, it should be truncated to zero bytes, and if it doesn't
+ *  exist, it should be created as a zero-byte file. The file pointer should
+ *  be positioned on the first byte of the file.
+ *
+ * The return value will be some platform-specific datatype that is opaque to
+ *  the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32,
+ *  etc.
+ *
+ * Opening a file for write multiple times has undefined results.
+ *
+ * Call __PHYSFS_setError() and return (NULL) if the file can't be opened.
+ */
+void *__PHYSFS_platformOpenWrite(const char *filename);
+
+/*
+ * Open a file for appending. (filename) is in platform-dependent notation. If
+ *  the file exists, the file pointer should be place just past the end of the
+ *  file, so that the first write will be one byte after the current end of
+ *  the file. If the file doesn't exist, it should be created as a zero-byte
+ *  file. The file pointer should be positioned on the first byte of the file.
+ *
+ * The return value will be some platform-specific datatype that is opaque to
+ *  the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32,
+ *  etc.
+ *
+ * Opening a file for append multiple times has undefined results.
+ *
+ * Call __PHYSFS_setError() and return (NULL) if the file can't be opened.
+ */
+void *__PHYSFS_platformOpenAppend(const char *filename);
+
+/*
+ * Read more data from a platform-specific file handle. (opaque) should be
+ *  cast to whatever data type your platform uses. Read a maximum of (count)
+ *  objects of (size) 8-bit bytes to the area pointed to by (buffer). If there
+ *  isn't enough data available, return the number of full objects read, and
+ *  position the file pointer at the start of the first incomplete object.
+ *  On success, return (count) and position the file pointer one byte past
+ *  the end of the last read object. Return (-1) if there is a catastrophic
+ *  error, and call __PHYSFS_setError() to describe the problem; the file
+ *  pointer should not move in such a case.
+ */
+PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
+                                    PHYSFS_uint32 size, PHYSFS_uint32 count);
+
+/*
+ * Write more data to a platform-specific file handle. (opaque) should be
+ *  cast to whatever data type your platform uses. Write a maximum of (count)
+ *  objects of (size) 8-bit bytes from the area pointed to by (buffer). If
+ *  there isn't enough data available, return the number of full objects
+ *  written, and position the file pointer at the start of the first
+ *  incomplete object. Return (-1) if there is a catastrophic error, and call
+ *  __PHYSFS_setError() to describe the problem; the file pointer should not
+ *  move in such a case.
+ */
+PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, void *buffer,
+                                     PHYSFS_uint32 size, PHYSFS_uint32 count);
+
+/*
+ * Set the file pointer to a new position. (opaque) should be cast to
+ *  whatever data type your platform uses. (pos) specifies the number
+ *  of 8-bit bytes to seek to from the start of the file. Seeking past the
+ *  end of the file is an error condition, and you should check for it.
+ *
+ * Not all file types can seek; this is to be expected by the caller.
+ *
+ * On error, call __PHYSFS_setError() and return zero. On success, return
+ *  a non-zero value.
+ */
+int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos);
+
+/*
+ * Get the file pointer's position, in an 8-bit byte offset from the start of
+ *  the file. (opaque) should be cast to whatever data type your platform
+ *  uses.
+ *
+ * Not all file types can "tell"; this is to be expected by the caller.
+ *
+ * On error, call __PHYSFS_setError() and return zero. On success, return
+ *  a non-zero value.
+ */
+PHYSFS_sint64 __PHYSFS_platformTell(void *opaque);
+
+/*
+ * Determine the current size of a file, in 8-bit bytes, from an open file.
+ *
+ * The caller expects that this information may not be available for all
+ *  file types on all platforms.
+ *
+ * Return -1 if you can't do it, and call __PHYSFS_setError(). Otherwise,
+ *  return the file length in 8-bit bytes.
+ */
+PHYSFS_sint64 __PHYSFS_platformFileLength(void *handle);
+
+/*
+ * Determine if a file is at EOF. (opaque) should be cast to whatever data
+ *  type your platform uses.
+ *
+ * The caller expects that there was a short read before calling this.
+ *
+ * Return non-zero if EOF, zero if it is _not_ EOF.
+ */
+int __PHYSFS_platformEOF(void *opaque);
+
+/*
+ * Flush any pending writes to disk. (opaque) should be cast to whatever data
+ *  type your platform uses. Be sure to check for errors; the caller expects
+ *  that this function can fail if there was a flushing error, etc.
+ *
+ *  Return zero on failure, non-zero on success.
+ */
+int __PHYSFS_platformFlush(void *opaque);
+
+/*
+ * Flush and close a file. (opaque) should be cast to whatever data type
+ *  your platform uses. Be sure to check for errors when closing; the
+ *  caller expects that this function can fail if there was a flushing
+ *  error, etc.
+ *
+ * You should clean up all resources associated with (opaque).
+ *
+ *  Return zero on failure, non-zero on success.
+ */
+int __PHYSFS_platformClose(void *opaque);
+
+/*
  * Platform implementation of PHYSFS_getCdRomDirs()...
  *  See physfs.h. The retval should be freeable via PHYSFS_freeList().
  */
@@ -374,7 +522,7 @@
  *  arbitrary; the only requirement is that no two threads have the same
  *  number.
  */
-int __PHYSFS_platformGetThreadID(void);
+PHYSFS_uint64 __PHYSFS_platformGetThreadID(void);
 
 /*
  * This is a pass-through to whatever stricmp() is called on your platform.
@@ -413,7 +561,8 @@
  *  you can make assumptions about the size of strings, etc..
  *
  * Platforms that choose not to implement this may just call
- *  __PHYSFS_convertToDependent() as a passthrough.
+ *  __PHYSFS_convertToDependent() as a passthrough, which may fit the bill
+ *  already.
  *
  * Be sure to free() the return value when done with it.
  */
@@ -441,13 +590,6 @@
 
 
 /*
- * Determine the current size of a file, in bytes, from a stdio FILE *.
- *  Return -1 if you can't do it, and call __PHYSFS_setError().
- */
-int __PHYSFS_platformFileLength(FILE *handle);
-
-
-/*
  * Get the current working directory. The return value should be an
  *  absolute path in platform-dependent notation. The caller will deallocate
  *  the return value with the standard C runtime free() function when it
@@ -479,7 +621,7 @@
 
 
 #ifdef __cplusplus
-extern "C" {
+}
 #endif
 
 #endif
--- a/platform/unix.c	Sun Mar 24 19:42:21 2002 +0000
+++ b/platform/unix.c	Sun Mar 24 19:47:33 2002 +0000
@@ -282,9 +282,9 @@
 } /* __PHYSFS_platformGetUserDir */
 
 
-int __PHYSFS_platformGetThreadID(void)
+PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
 {
-    return((int) pthread_self());
+    return((PHYSFS_uint64) pthread_self());
 } /* __PHYSFS_platformGetThreadID */
 
 
@@ -481,15 +481,6 @@
 } /* __PHYSFS_platformEnumerateFiles */
 
 
-int __PHYSFS_platformFileLength(FILE *handle)
-{
-    struct stat statbuf;
-    errno = 0;
-    BAIL_IF_MACRO(fstat(fileno(handle), &statbuf) == -1, strerror(errno), -1);
-    return(statbuf.st_size);
-} /* __PHYSFS_platformFileLength */
-
-
 char *__PHYSFS_platformCurrentDir(void)
 {
     int allocSize = 0;
@@ -504,20 +495,24 @@
         {
             if (retval != NULL)
                 free(retval);
-            BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
+            BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
         } /* if */
-	
+
         retval = ptr;
         ptr = getcwd(retval, allocSize);
     } while (ptr == NULL && errno == ERANGE);
-    if(ptr == NULL && errno) {
-	/* getcwd() failed for some reason, for example current
-	 * directory not existing.
-	 */
-	if (retval != NULL)
-	    free(retval);
-	BAIL_IF_MACRO(1, ERR_NO_SUCH_FILE, NULL);
-    }
+
+    if (ptr == NULL && errno)
+    {
+            /*
+             * getcwd() failed for some reason, for example current
+             * directory not existing.
+             */
+        if (retval != NULL)
+            free(retval);
+        BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
+    } /* if */
+
     return(retval);
 } /* __PHYSFS_platformCurrentDir */
 
@@ -545,5 +540,118 @@
     return(1);
 } /* __PHYSFS_platformMkDir */
 
+
+static void *doOpen(const char *filename, const char *mode)
+{
+    FILE *retval;
+    errno = 0;
+
+    retval = fopen(filename, mode);
+    if (retval == NULL)
+        __PHYSFS_setError(strerror(errno));
+
+    return((void *) retval);
+} /* doOpen */
+
+
+void *__PHYSFS_platformOpenRead(const char *filename)
+{
+    return(doOpen(filename, "rb"));
+} /* __PHYSFS_platformOpenRead */
+
+
+void *__PHYSFS_platformOpenWrite(const char *filename)
+{
+    return(doOpen(filename, "wb"));
+} /* __PHYSFS_platformOpenWrite */
+
+
+void *__PHYSFS_platformOpenAppend(const char *filename)
+{
+    return(doOpen(filename, "wb+"));
+} /* __PHYSFS_platformOpenAppend */
+
+
+PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
+                                    PHYSFS_uint32 size, PHYSFS_uint32 count)
+{
+    FILE *io = (FILE *) opaque;
+    int rc = fread(buffer, size, count, io);
+    if (rc < count)
+    {
+        int err = errno;
+        BAIL_IF_MACRO(ferror(io), strerror(err), rc);
+        BAIL_MACRO(ERR_PAST_EOF, rc);
+    } /* if */
+
+    return(rc);
+} /* __PHYSFS_platformRead */
+
+
+PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, void *buffer,
+                                     PHYSFS_uint32 size, PHYSFS_uint32 count)
+{
+    FILE *io = (FILE *) opaque;
+    int rc = fwrite(buffer, size, count, io);
+    if (rc < count)
+        __PHYSFS_setError(strerror(errno));
+
+    return(rc);
+} /* __PHYSFS_platformWrite */
+
+
+int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
+{
+    FILE *io = (FILE *) opaque;
+
+    /* !!! FIXME: Use llseek where available. */
+    errno = 0;
+    BAIL_IF_MACRO(fseek(io, pos, SEEK_SET) != 0, strerror(errno), 0);
+
+    return(1);
+} /* __PHYSFS_platformSeek */
+
+
+PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
+{
+    FILE *io = (FILE *) opaque;
+    PHYSFS_sint64 retval = ftell(io);
+    BAIL_IF_MACRO(retval == -1, strerror(errno), -1);
+    return(retval);
+} /* __PHYSFS_platformTell */
+
+
+PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
+{
+    FILE *io = (FILE *) opaque;
+    struct stat statbuf;
+    errno = 0;
+    BAIL_IF_MACRO(fstat(fileno(io), &statbuf) == -1, strerror(errno), -1);
+    return((PHYSFS_sint64) statbuf.st_size);
+} /* __PHYSFS_platformFileLength */
+
+
+int __PHYSFS_platformEOF(void *opaque)
+{
+    return(feof((FILE *) opaque));
+} /* __PHYSFS_platformEOF */
+
+
+int __PHYSFS_platformFlush(void *opaque)
+{
+    int rc = fflush((FILE *) opaque);
+    BAIL_IF_MACRO(rc == EOF, strerror(errno), 0);
+    return(1);
+} /* __PHYSFS_platformFlush */
+
+
+int __PHYSFS_platformClose(void *opaque)
+{
+    int rc = fclose((FILE *) opaque);
+    BAIL_IF_MACRO(rc == EOF, strerror(errno), 0);
+    return(1);
+} /* __PHYSFS_platformClose */
+
+
 /* end of unix.c ... */
 
--- a/test/test_physfs.c	Sun Mar 24 19:42:21 2002 +0000
+++ b/test/test_physfs.c	Sun Mar 24 19:47:33 2002 +0000
@@ -41,8 +41,8 @@
            " Compiled against PhysicsFS version %d.%d.%d,\n"
            " and linked against %d.%d.%d.\n\n",
             TEST_VERSION_MAJOR, TEST_VERSION_MINOR, TEST_VERSION_PATCH,
-            compiled.major, compiled.minor, compiled.patch,
-            linked.major, linked.minor, linked.patch);
+            (int) compiled.major, (int) compiled.minor, (int) compiled.patch,
+            (int) linked.major, (int) linked.minor, (int) linked.patch);
 } /* output_versions */
 
 
@@ -336,8 +336,8 @@
         while (1)
         {
             char buffer[128];
-            int rc;
-            int i;
+            PHYSFS_sint64 rc;
+            PHYSFS_sint64 i;
             rc = PHYSFS_read(f, buffer, 1, sizeof (buffer));
 
             for (i = 0; i < rc; i++)
@@ -347,7 +347,10 @@
             {
                 printf("\n\n");
                 if (!PHYSFS_eof(f))
-                    printf("\n (Error condition in reading.)\n\n");
+                {
+                    printf("\n (Error condition in reading. Reason: [%s])\n\n",
+                           PHYSFS_getLastError());
+                } /* if */
                 PHYSFS_close(f);
                 return(1);
             } /* if */