Moved all the file i/o from stdio-style to POSIX-style.
authorRyan C. Gordon <icculus@icculus.org>
Sat, 21 Aug 2010 02:47:58 -0400
changeset 1098 4e86cec1143f
parent 1097 6e67897d4628
child 1099 fd12454c37ee
Moved all the file i/o from stdio-style to POSIX-style. Instead of trying to deal with a count of objects, just give 'em a stream of bytes. This is WAY simpler to work with at the implementation level, and removes confusion about what to do with a partial read. This will be very useful when we expose the i/o interface to applications.
src/archiver_dir.c
src/archiver_grp.c
src/archiver_hog.c
src/archiver_iso9660.c
src/archiver_lzma.c
src/archiver_mvl.c
src/archiver_qpak.c
src/archiver_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/src/archiver_dir.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/archiver_dir.c	Sat Aug 21 02:47:58 2010 -0400
@@ -14,21 +14,15 @@
 #define __PHYSICSFS_INTERNAL__
 #include "physfs_internal.h"
 
-static PHYSFS_sint64 DIR_read(fvoid *opaque, void *buffer,
-                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 DIR_read(fvoid *opaque, void *buffer, PHYSFS_uint64 len)
 {
-    PHYSFS_sint64 retval;
-    retval = __PHYSFS_platformRead(opaque, buffer, objSize, objCount);
-    return retval;
+    return __PHYSFS_platformRead(opaque, buffer, len);
 } /* DIR_read */
 
 
-static PHYSFS_sint64 DIR_write(fvoid *opaque, const void *buffer,
-                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 DIR_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
 {
-    PHYSFS_sint64 retval;
-    retval = __PHYSFS_platformWrite(opaque, buffer, objSize, objCount);
-    return retval;
+    return __PHYSFS_platformWrite(f, buf, len);
 } /* DIR_write */
 
 
--- a/src/archiver_grp.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/archiver_grp.c	Sat Aug 21 02:47:58 2010 -0400
@@ -57,6 +57,12 @@
 } GRPfileinfo;
 
 
+static inline int readAll(void *fh, void *buf, const PHYSFS_uint64 len)
+{
+    return (__PHYSFS_platformRead(fh, buf, len) == len);
+} /* readAll */
+
+
 static void GRP_dirClose(dvoid *opaque)
 {
     GRPinfo *info = ((GRPinfo *) opaque);
@@ -66,28 +72,25 @@
 } /* GRP_dirClose */
 
 
-static PHYSFS_sint64 GRP_read(fvoid *opaque, void *buffer,
-                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 GRP_read(fvoid *opaque, void *buffer, PHYSFS_uint64 len)
 {
     GRPfileinfo *finfo = (GRPfileinfo *) opaque;
-    GRPentry *entry = finfo->entry;
-    PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
-    PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
+    const GRPentry *entry = finfo->entry;
+    const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos);
     PHYSFS_sint64 rc;
 
-    if (objsLeft < objCount)
-        objCount = objsLeft;
+    if (bytesLeft < len)
+        len = bytesLeft;
 
-    rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
+    rc = __PHYSFS_platformRead(finfo->handle, buffer, len);
     if (rc > 0)
-        finfo->curPos += (PHYSFS_uint32) (rc * objSize);
+        finfo->curPos += (PHYSFS_uint32) rc;
 
     return rc;
 } /* GRP_read */
 
 
-static PHYSFS_sint64 GRP_write(fvoid *opaque, const void *buffer,
-                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 GRP_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
 {
     BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
 } /* GRP_write */
@@ -150,7 +153,7 @@
     *fh = __PHYSFS_platformOpenRead(filename);
     BAIL_IF_MACRO(*fh == NULL, NULL, 0);
     
-    if (__PHYSFS_platformRead(*fh, buf, 12, 1) != 1)
+    if (!readAll(*fh, buf, 12))
         goto openGrp_failed;
 
     if (memcmp(buf, "KenSilverman", 12) != 0)
@@ -159,7 +162,7 @@
         goto openGrp_failed;
     } /* if */
 
-    if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
+    if (!readAll(*fh, count, sizeof (PHYSFS_uint32)))
         goto openGrp_failed;
 
     *count = PHYSFS_swapULE32(*count);
@@ -236,7 +239,8 @@
 
     for (entry = info->entries; fileCount > 0; fileCount--, entry++)
     {
-        if (__PHYSFS_platformRead(fh, &entry->name, 12, 1) != 1)
+        if ( (!readAll(fh, &entry->name, 12)) ||
+             (!readAll(fh, &entry->size, sizeof (PHYSFS_uint32))) )
         {
             __PHYSFS_platformClose(fh);
             return 0;
@@ -246,12 +250,6 @@
         if ((ptr = strchr(entry->name, ' ')) != NULL)
             *ptr = '\0';  /* trim extra spaces. */
 
-        if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
-        {
-            __PHYSFS_platformClose(fh);
-            return 0;
-        } /* if */
-
         entry->size = PHYSFS_swapULE32(entry->size);
         entry->startPos = location;
         location += entry->size;
--- a/src/archiver_hog.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/archiver_hog.c	Sat Aug 21 02:47:58 2010 -0400
@@ -71,6 +71,12 @@
 } HOGfileinfo;
 
 
+static inline int readAll(void *fh, void *buf, const PHYSFS_uint64 len)
+{
+    return (__PHYSFS_platformRead(fh, buf, len) == len);
+} /* readAll */
+
+
 static void HOG_dirClose(dvoid *opaque)
 {
     HOGinfo *info = ((HOGinfo *) opaque);
@@ -80,28 +86,25 @@
 } /* HOG_dirClose */
 
 
-static PHYSFS_sint64 HOG_read(fvoid *opaque, void *buffer,
-                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 HOG_read(fvoid *opaque, void *buffer, PHYSFS_uint64 len)
 {
     HOGfileinfo *finfo = (HOGfileinfo *) opaque;
-    HOGentry *entry = finfo->entry;
-    PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
-    PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
+    const HOGentry *entry = finfo->entry;
+    const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos);
     PHYSFS_sint64 rc;
 
-    if (objsLeft < objCount)
-        objCount = objsLeft;
+    if (bytesLeft < len)
+        len = bytesLeft;
 
-    rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
+    rc = __PHYSFS_platformRead(finfo->handle, buffer, len);
     if (rc > 0)
-        finfo->curPos += (PHYSFS_uint32) (rc * objSize);
+        finfo->curPos += (PHYSFS_uint32) rc;
 
     return rc;
 } /* HOG_read */
 
 
-static PHYSFS_sint64 HOG_write(fvoid *opaque, const void *buffer,
-                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 HOG_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
 {
     BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
 } /* HOG_write */
@@ -168,7 +171,7 @@
     *fh = __PHYSFS_platformOpenRead(filename);
     BAIL_IF_MACRO(*fh == NULL, NULL, 0);
 
-    if (__PHYSFS_platformRead(*fh, buf, 3, 1) != 1)
+    if (!readAll(*fh, buf, 3))
         goto openHog_failed;
 
     if (memcmp(buf, "DHF", 3) != 0)
@@ -179,10 +182,10 @@
 
     while (1)
     {
-        if (__PHYSFS_platformRead(*fh, buf, 13, 1) != 1)
+        if (!readAll(*fh, buf, 13))
             break; /* eof here is ok */
 
-        if (__PHYSFS_platformRead(*fh, &size, 4, 1) != 1)
+        if (!readAll(*fh, &size, sizeof (PHYSFS_uint32)))
             goto openHog_failed;
 
         size = PHYSFS_swapULE32(size);
@@ -269,13 +272,8 @@
 
     for (entry = info->entries; fileCount > 0; fileCount--, entry++)
     {
-        if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
-        {
-            __PHYSFS_platformClose(fh);
-            return 0;
-        } /* if */
-
-        if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
+        if ( (!readAll(fh, &entry->name, 13)) ||
+             (!readAll(fh, &entry->size, sizeof (PHYSFS_uint32))) )
         {
             __PHYSFS_platformClose(fh);
             return 0;
@@ -283,18 +281,14 @@
 
         entry->size = PHYSFS_swapULE32(entry->size);
         entry->startPos = (unsigned int) __PHYSFS_platformTell(fh);
-        if (entry->startPos == -1)
+
+        /* Skip over entry */
+        if ( (entry->startPos == -1) ||
+             (!__PHYSFS_platformSeek(fh, entry->startPos + entry->size)) )
         {
             __PHYSFS_platformClose(fh);
             return 0;
-        }
-
-        /* Skip over entry */
-        if (!__PHYSFS_platformSeek(fh, entry->startPos + entry->size))
-        {
-            __PHYSFS_platformClose(fh);
-            return 0;
-        }
+        } /* if */
     } /* for */
 
     __PHYSFS_platformClose(fh);
--- a/src/archiver_iso9660.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/archiver_iso9660.c	Sat Aug 21 02:47:58 2010 -0400
@@ -217,7 +217,7 @@
     PHYSFS_uint64 startblock;
     ISO9660Handle *isohandle;
     PHYSFS_uint32 (*read) (struct __ISO9660FileHandle *filehandle, void *buffer,
-            PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+            PHYSFS_uint64 len);
     int (*seek)(struct __ISO9660FileHandle *filehandle,  PHYSFS_sint64 offset);
     int (*close)(struct __ISO9660FileHandle *filehandle);
     /* !!! FIXME: anonymouse union is going to cause problems. */
@@ -343,8 +343,7 @@
  ******************************************************************************/
 
 static int iso_readimage(ISO9660Handle *handle, PHYSFS_uint64 where,
-                         void *buffer, PHYSFS_uint32 objSize,
-                         PHYSFS_uint32 objCount)
+                         void *buffer, PHYSFS_uint64 len)
 {
     BAIL_IF_MACRO(!__PHYSFS_platformGrabMutex(handle->mutex),
             ERR_LOCK_VIOLATION, -1);
@@ -352,13 +351,13 @@
     if (where != handle->currpos)
         GOTO_IF_MACRO(!__PHYSFS_platformSeek(handle->fhandle,where), NULL,
                 unlockme);
-    rc = __PHYSFS_platformRead(handle->fhandle, buffer, objSize, objCount);
+    rc = __PHYSFS_platformRead(handle->fhandle, buffer, len);
     if (rc == -1)
     {
         handle->currpos = (PHYSFS_uint64) -1;
         GOTO_MACRO(NULL, unlockme);
     } /* if */
-    handle->currpos += rc * objSize;
+    handle->currpos += rc;
 
     unlockme:
     __PHYSFS_platformReleaseMutex(handle->mutex);
@@ -371,7 +370,7 @@
                                             ISO9660FileDescriptor *descriptor)
 {
     PHYSFS_sint64 rc = iso_readimage(handle, where, descriptor,
-                                     sizeof (descriptor->recordlen), 1);
+                                     sizeof (descriptor->recordlen));
     BAIL_IF_MACRO(rc == -1, NULL, -1);
     BAIL_IF_MACRO(rc != 1, ERR_CORRUPTED, -1);
 
@@ -379,7 +378,7 @@
         return 0; /* fill bytes at the end of a sector */
 
     rc = iso_readimage(handle, where + 1, &descriptor->extattributelen,
-            descriptor->recordlen - sizeof(descriptor->recordlen), 1);
+            descriptor->recordlen - sizeof(descriptor->recordlen));
     BAIL_IF_MACRO(rc == -1, NULL, -1);
     BAIL_IF_MACRO(rc != 1, ERR_CORRUPTED, -1);
 
@@ -476,7 +475,7 @@
                                    ISO9660ExtAttributeRec *attributes)
 {
     return iso_readimage(handle, block * 2048, attributes,
-                         sizeof(ISO9660ExtAttributeRec), 1);
+                         sizeof(ISO9660ExtAttributeRec));
 } /* iso_read_ext_attributes */
 
 
@@ -502,7 +501,7 @@
     } /* if */
 
     /* Read magic number */
-    if (__PHYSFS_platformRead(in, magicnumber, 5, 1) != 1)
+    if (__PHYSFS_platformRead(in, magicnumber, 5) != 5)
     {
         __PHYSFS_platformClose(in); /* Don't forget to close the file before returning... */
         BAIL_MACRO(NULL, 0);
@@ -543,7 +542,7 @@
     while (1)
     {
         ISO9660VolumeDescriptor descriptor;
-        GOTO_IF_MACRO(__PHYSFS_platformRead(handle->fhandle, &descriptor, sizeof(ISO9660VolumeDescriptor),1) != 1, "Cannot read from image", errorcleanup);
+        GOTO_IF_MACRO(__PHYSFS_platformRead(handle->fhandle, &descriptor, sizeof(ISO9660VolumeDescriptor)) != sizeof(ISO9660VolumeDescriptor), "Cannot read from image", errorcleanup);
         GOTO_IF_MACRO(strncmp(descriptor.identifier, "CD001", 5) != 0, ERR_NOT_AN_ARCHIVE, errorcleanup);
 
         if (descriptor.type == 255)
@@ -618,22 +617,20 @@
 
 
 static PHYSFS_uint32 iso_file_read_mem(ISO9660FileHandle *filehandle,
-                                       void *buffer, PHYSFS_uint32 objSize,
-                                       PHYSFS_uint32 objCount)
+                                       void *buffer, PHYSFS_uint64 len)
 {
     /* check remaining bytes & max obj which can be fetched */
-    PHYSFS_sint64 bytesleft = filehandle->filesize - filehandle->currpos;
-    PHYSFS_uint64 maxObjs = bytesleft / objSize;
-    if (maxObjs < objCount)
-        objCount = maxObjs;
+    const PHYSFS_sint64 bytesleft = filehandle->filesize - filehandle->currpos;
+    if (bytesleft < len)
+        len = bytesleft;
 
-    if (objCount == 0)
+    if (len == 0)
         return 0;
 
-    memcpy(buffer, filehandle->cacheddata + filehandle->currpos,
-            objCount * objSize);
-    filehandle->currpos += objSize * objCount;
-    return objCount;
+    memcpy(buffer, filehandle->cacheddata + filehandle->currpos, (size_t) len);
+
+    filehandle->currpos += len;
+    return (PHYSFS_uint32) len;
 } /* iso_file_read_mem */
 
 
@@ -656,21 +653,19 @@
 
 
 static PHYSFS_uint32 iso_file_read_foreign(ISO9660FileHandle *filehandle,
-                                           void *buffer, PHYSFS_uint32 objSize,
-                                           PHYSFS_uint32 objCount)
+                                           void *buffer, PHYSFS_uint64 len)
 {
     /* check remaining bytes & max obj which can be fetched */
-    PHYSFS_sint64 bytesleft = filehandle->filesize - filehandle->currpos;
-    PHYSFS_uint64 maxObjs = bytesleft / objSize;
-    if (maxObjs < objCount)
-        objCount = maxObjs;
+    const PHYSFS_sint64 bytesleft = filehandle->filesize - filehandle->currpos;
+    if (bytesleft < len)
+        len = bytesleft;
 
     PHYSFS_sint64 rc =  __PHYSFS_platformRead(filehandle->filehandle, buffer,
-                                              objSize, objCount);
+                                              len);
     BAIL_IF_MACRO(rc == -1, NULL, -1);
 
-    filehandle->currpos += rc * objSize; /* i trust my internal book keeping */
-    BAIL_IF_MACRO(rc < objCount, ERR_CORRUPTED, -1);
+    filehandle->currpos += rc; /* i trust my internal book keeping */
+    BAIL_IF_MACRO(rc < len, ERR_CORRUPTED, -1);
     return rc;
 } /* iso_file_read_foreign */
 
@@ -703,7 +698,7 @@
     fhandle->cacheddata = allocator.Malloc(fhandle->filesize);
     BAIL_IF_MACRO(!fhandle->cacheddata, ERR_OUT_OF_MEMORY, -1);
     int rc = iso_readimage(handle, fhandle->startblock * 2048,
-                           fhandle->cacheddata, fhandle->filesize, 1);
+                           fhandle->cacheddata, fhandle->filesize);
     GOTO_IF_MACRO(rc < 0, NULL, freemem);
     GOTO_IF_MACRO(rc == 0, ERR_CORRUPTED, freemem);
 
@@ -783,12 +778,10 @@
     return fhandle->close(fhandle);
 } /* ISO9660_fileClose */
 
-static PHYSFS_sint64 ISO9660_read(fvoid *opaque, void *buffer,
-                                  PHYSFS_uint32 objSize,
-                                  PHYSFS_uint32 objCount)
+static PHYSFS_sint64 ISO9660_read(fvoid *opaque, void *buf, PHYSFS_uint64 len)
 {
     ISO9660FileHandle *fhandle = (ISO9660FileHandle*) opaque;
-    return fhandle->read(fhandle, buffer, objSize, objCount);
+    return fhandle->read(fhandle, buf, len);
 } /* ISO9660_read */
 
 
@@ -985,9 +978,7 @@
 } /* ISO9660_mkdir */
 
 
-static PHYSFS_sint64 ISO9660_write(fvoid *opaque, const void *buffer,
-                                   PHYSFS_uint32 objSize,
-                                   PHYSFS_uint32 objCount)
+static PHYSFS_sint64 ISO9660_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
 {
     BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
 } /* ISO9660_write */
--- a/src/archiver_lzma.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/archiver_lzma.c	Sat Aug 21 02:47:58 2010 -0400
@@ -113,7 +113,7 @@
 
     if (maxReqSize > BUFFER_SIZE)
         maxReqSize = BUFFER_SIZE;
-    processedSizeLoc = __PHYSFS_platformRead(s->file, s->buffer, 1, maxReqSize);
+    processedSizeLoc = __PHYSFS_platformRead(s->file, s->buffer, maxReqSize);
     *buffer = s->buffer;
     if (processedSize != NULL)
         *processedSize = (size_t) processedSizeLoc;
@@ -131,7 +131,7 @@
                         size_t *processedSize)
 {
     FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
-    size_t processedSizeLoc = __PHYSFS_platformRead(s->file, buffer, 1, size);
+    size_t processedSizeLoc = __PHYSFS_platformRead(s->file, buffer, size);
     if (processedSize != 0)
         *processedSize = processedSizeLoc;
     return SZ_OK;
@@ -322,25 +322,19 @@
 } /* lzma_err */
 
 
-static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer,
-                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuf, PHYSFS_uint64 len)
 {
     LZMAfile *file = (LZMAfile *) opaque;
 
-    size_t wantedSize = objSize*objCount;
+    size_t wantedSize = (size_t) len;
     size_t remainingSize = file->item->Size - file->position;
     size_t fileSize = 0;
 
     BAIL_IF_MACRO(wantedSize == 0, NULL, 0); /* quick rejection. */
     BAIL_IF_MACRO(remainingSize == 0, ERR_PAST_EOF, 0);
 
-    if (remainingSize < wantedSize)
-    {
-        wantedSize = remainingSize - (remainingSize % objSize);
-        objCount = (PHYSFS_uint32) (remainingSize / objSize);
-        BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */
-        __PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */
-    } /* if */
+    if (wantedSize > remainingSize)
+        wantedSize = remainingSize;
 
     /* Only decompress the folder if it is not allready cached */
     if (file->folder->cache == NULL)
@@ -365,19 +359,18 @@
             return -1;
     } /* if */
 
-    /* Copy wanted bytes over from cache to outBuffer */
-    memcpy(outBuffer,
+    /* Copy wanted bytes over from cache to outBuf */
+    memcpy(outBuf,
             (file->folder->cache +
                     file->offset + file->position),
             wantedSize);
     file->position += wantedSize; /* Increase virtual position */
 
-    return objCount;
+    return wantedSize;
 } /* LZMA_read */
 
 
-static PHYSFS_sint64 LZMA_write(fvoid *opaque, const void *buf,
-                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 LZMA_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
 {
     BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
 } /* LZMA_write */
@@ -448,7 +441,7 @@
     BAIL_IF_MACRO(in == NULL, NULL, 0);
 
     /* Read signature bytes */
-    if (__PHYSFS_platformRead(in, sig, k7zSignatureSize, 1) != 1)
+    if (__PHYSFS_platformRead(in, sig, k7zSignatureSize) != k7zSignatureSize)
     {
         __PHYSFS_platformClose(in); /* Don't forget to close the file before returning... */
         BAIL_MACRO(NULL, 0);
--- a/src/archiver_mvl.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/archiver_mvl.c	Sat Aug 21 02:47:58 2010 -0400
@@ -69,28 +69,25 @@
 } /* MVL_dirClose */
 
 
-static PHYSFS_sint64 MVL_read(fvoid *opaque, void *buffer,
-                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 MVL_read(fvoid *opaque, void *buffer, PHYSFS_uint64 len)
 {
     MVLfileinfo *finfo = (MVLfileinfo *) opaque;
-    MVLentry *entry = finfo->entry;
-    PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
-    PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
+    const MVLentry *entry = finfo->entry;
+    const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos);
     PHYSFS_sint64 rc;
 
-    if (objsLeft < objCount)
-        objCount = objsLeft;
+    if (bytesLeft < len)
+        len = bytesLeft;
 
-    rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
+    rc = __PHYSFS_platformRead(finfo->handle, buffer, len);
     if (rc > 0)
-        finfo->curPos += (PHYSFS_uint32) (rc * objSize);
+        finfo->curPos += (PHYSFS_uint32) rc;
 
     return rc;
 } /* MVL_read */
 
 
-static PHYSFS_sint64 MVL_write(fvoid *opaque, const void *buffer,
-                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 MVL_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
 {
     BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
 } /* MVL_write */
@@ -153,7 +150,7 @@
     *fh = __PHYSFS_platformOpenRead(filename);
     BAIL_IF_MACRO(*fh == NULL, NULL, 0);
     
-    if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
+    if (__PHYSFS_platformRead(*fh, buf, 4) != 4)
         goto openMvl_failed;
 
     if (memcmp(buf, "DMVL", 4) != 0)
@@ -162,7 +159,7 @@
         goto openMvl_failed;
     } /* if */
 
-    if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
+    if (__PHYSFS_platformRead(*fh, count, 4) != 4)
         goto openMvl_failed;
 
     *count = PHYSFS_swapULE32(*count);
@@ -238,13 +235,13 @@
 
     for (entry = info->entries; fileCount > 0; fileCount--, entry++)
     {
-        if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
+        if (__PHYSFS_platformRead(fh, &entry->name, 13) != 13)
         {
             __PHYSFS_platformClose(fh);
             return 0;
         } /* if */
 
-        if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
+        if (__PHYSFS_platformRead(fh, &entry->size, 4) != 4)
         {
             __PHYSFS_platformClose(fh);
             return 0;
--- a/src/archiver_qpak.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/archiver_qpak.c	Sat Aug 21 02:47:58 2010 -0400
@@ -83,28 +83,25 @@
 } /* QPAK_dirClose */
 
 
-static PHYSFS_sint64 QPAK_read(fvoid *opaque, void *buffer,
-                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 QPAK_read(fvoid *opaque, void *buffer, PHYSFS_uint64 len)
 {
     QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
-    QPAKentry *entry = finfo->entry;
-    PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
-    PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
+    const QPAKentry *entry = finfo->entry;
+    const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos);
     PHYSFS_sint64 rc;
 
-    if (objsLeft < objCount)
-        objCount = objsLeft;
+    if (bytesLeft < len)
+        len = bytesLeft;
 
-    rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
+    rc = __PHYSFS_platformRead(finfo->handle, buffer, len);
     if (rc > 0)
-        finfo->curPos += (PHYSFS_uint32) (rc * objSize);
+        finfo->curPos += (PHYSFS_uint32) rc;
 
     return rc;
 } /* QPAK_read */
 
 
-static PHYSFS_sint64 QPAK_write(fvoid *opaque, const void *buffer,
-                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 QPAK_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
 {
     BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
 } /* QPAK_write */
@@ -156,6 +153,11 @@
 } /* QPAK_fileClose */
 
 
+static inline int readAll(void *fh, void *buf, const PHYSFS_uint64 len)
+{
+    return (__PHYSFS_platformRead(fh, buf, len) == len);
+} /* readAll */
+
 static int qpak_open(const char *filename, int forWriting,
                     void **fh, PHYSFS_uint32 *count)
 {
@@ -167,18 +169,18 @@
     *fh = __PHYSFS_platformOpenRead(filename);
     BAIL_IF_MACRO(*fh == NULL, NULL, 0);
     
-    if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
+    if (!readAll(*fh, &buf, sizeof (PHYSFS_uint32)))
         goto openQpak_failed;
 
     buf = PHYSFS_swapULE32(buf);
     GOTO_IF_MACRO(buf != QPAK_SIG, ERR_UNSUPPORTED_ARCHIVE, openQpak_failed);
 
-    if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
+    if (!readAll(*fh, &buf, sizeof (PHYSFS_uint32)))
         goto openQpak_failed;
 
     buf = PHYSFS_swapULE32(buf);  /* directory table offset. */
 
-    if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
+    if (!readAll(*fh, count, sizeof (PHYSFS_uint32)))
         goto openQpak_failed;
 
     *count = PHYSFS_swapULE32(*count);
@@ -258,28 +260,16 @@
 
     for (entry = info->entries; fileCount > 0; fileCount--, entry++)
     {
-        PHYSFS_uint32 loc;
-
-        if (__PHYSFS_platformRead(fh,&entry->name,sizeof(entry->name),1) != 1)
-        {
-            __PHYSFS_platformClose(fh);
-            return 0;
-        } /* if */
-
-        if (__PHYSFS_platformRead(fh,&loc,sizeof(loc),1) != 1)
-        {
-            __PHYSFS_platformClose(fh);
-            return 0;
-        } /* if */
-
-        if (__PHYSFS_platformRead(fh,&entry->size,sizeof(entry->size),1) != 1)
+        if ( (!readAll(fh, &entry->name, sizeof (entry->name))) ||
+             (!readAll(fh, &entry->startPos, sizeof (entry->startPos))) ||
+             (!readAll(fh, &entry->size, sizeof(entry->size))) )
         {
             __PHYSFS_platformClose(fh);
             return 0;
         } /* if */
 
         entry->size = PHYSFS_swapULE32(entry->size);
-        entry->startPos = PHYSFS_swapULE32(loc);
+        entry->startPos = PHYSFS_swapULE32(entry->startPos);
     } /* for */
 
     __PHYSFS_platformClose(fh);
--- a/src/archiver_wad.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/archiver_wad.c	Sat Aug 21 02:47:58 2010 -0400
@@ -85,28 +85,25 @@
 } /* WAD_dirClose */
 
 
-static PHYSFS_sint64 WAD_read(fvoid *opaque, void *buffer,
-                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 WAD_read(fvoid *opaque, void *buffer, PHYSFS_uint64 len)
 {
     WADfileinfo *finfo = (WADfileinfo *) opaque;
-    WADentry *entry = finfo->entry;
-    PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
-    PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
+    const WADentry *entry = finfo->entry;
+    const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos);
     PHYSFS_sint64 rc;
 
-    if (objsLeft < objCount)
-        objCount = objsLeft;
+    if (bytesLeft < len)
+        len = bytesLeft;
 
-    rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
+    rc = __PHYSFS_platformRead(finfo->handle, buffer, len);
     if (rc > 0)
-        finfo->curPos += (PHYSFS_uint32) (rc * objSize);
+        finfo->curPos += (PHYSFS_uint32) rc;
 
     return rc;
 } /* WAD_read */
 
 
-static PHYSFS_sint64 WAD_write(fvoid *opaque, const void *buffer,
-                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 WAD_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
 {
     BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
 } /* WAD_write */
@@ -158,6 +155,12 @@
 } /* WAD_fileClose */
 
 
+static inline int readAll(void *fh, void *buf, const PHYSFS_uint64 len)
+{
+    return (__PHYSFS_platformRead(fh, buf, len) == len);
+} /* readAll */
+
+
 static int wad_open(const char *filename, int forWriting,
                     void **fh, PHYSFS_uint32 *count,PHYSFS_uint32 *offset)
 {
@@ -169,7 +172,7 @@
     *fh = __PHYSFS_platformOpenRead(filename);
     BAIL_IF_MACRO(*fh == NULL, NULL, 0);
     
-    if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
+    if (!readAll(*fh, buf, 4))
         goto openWad_failed;
 
     if (memcmp(buf, "IWAD", 4) != 0 && memcmp(buf, "PWAD", 4) != 0)
@@ -178,12 +181,12 @@
         goto openWad_failed;
     } /* if */
 
-    if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
+    if (!readAll(*fh, count, sizeof (PHYSFS_uint32)))
         goto openWad_failed;
 
     *count = PHYSFS_swapULE32(*count);
 
-    if (__PHYSFS_platformRead(*fh, offset, sizeof (PHYSFS_uint32), 1) != 1)
+    if (!readAll(*fh, offset, sizeof (PHYSFS_uint32)))
         goto openWad_failed;
 
     *offset = PHYSFS_swapULE32(*offset);
@@ -262,19 +265,9 @@
 
     for (entry = info->entries; fileCount > 0; fileCount--, entry++)
     {
-        if (__PHYSFS_platformRead(fh, &entry->startPos, 4, 1) != 1)
-        {
-            __PHYSFS_platformClose(fh);
-            return 0;
-        } /* if */
-        
-        if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
-        {
-            __PHYSFS_platformClose(fh);
-            return 0;
-        } /* if */
-
-        if (__PHYSFS_platformRead(fh, &entry->name, 8, 1) != 1)
+        if ( (!readAll(fh, &entry->startPos, sizeof (PHYSFS_uint32))) ||
+             (!readAll(fh, &entry->size, sizeof (PHYSFS_uint32))) ||
+             (!readAll(fh, &entry->name, 8)) )
         {
             __PHYSFS_platformClose(fh);
             return 0;
--- a/src/archiver_zip.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/archiver_zip.c	Sat Aug 21 02:47:58 2010 -0400
@@ -172,13 +172,18 @@
 } /* zlib_err */
 
 
+static inline int readAll(void *fh, void *buf, const PHYSFS_uint64 len)
+{
+    return (__PHYSFS_platformRead(fh, buf, len) == len);
+} /* readAll */
+
 /*
  * Read an unsigned 32-bit int and swap to native byte order.
  */
 static int readui32(void *in, PHYSFS_uint32 *val)
 {
     PHYSFS_uint32 v;
-    BAIL_IF_MACRO(__PHYSFS_platformRead(in, &v, sizeof (v), 1) != 1, NULL, 0);
+    BAIL_IF_MACRO(!readAll(in, &v, sizeof (v)), NULL, 0);
     *val = PHYSFS_swapULE32(v);
     return 1;
 } /* readui32 */
@@ -190,41 +195,32 @@
 static int readui16(void *in, PHYSFS_uint16 *val)
 {
     PHYSFS_uint16 v;
-    BAIL_IF_MACRO(__PHYSFS_platformRead(in, &v, sizeof (v), 1) != 1, NULL, 0);
+    BAIL_IF_MACRO(!readAll(in, &v, sizeof (v)), NULL, 0);
     *val = PHYSFS_swapULE16(v);
     return 1;
 } /* readui16 */
 
 
-static PHYSFS_sint64 ZIP_read(fvoid *opaque, void *buf,
-                              PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 ZIP_read(fvoid *opaque, void *buf, PHYSFS_uint64 len)
 {
     ZIPfileinfo *finfo = (ZIPfileinfo *) opaque;
     ZIPentry *entry = finfo->entry;
     PHYSFS_sint64 retval = 0;
-    PHYSFS_sint64 maxread = ((PHYSFS_sint64) objSize) * objCount;
+    PHYSFS_sint64 maxread = (PHYSFS_sint64) len;
     PHYSFS_sint64 avail = entry->uncompressed_size -
                           finfo->uncompressed_position;
 
+    if (avail < maxread)
+        maxread = avail;
+
     BAIL_IF_MACRO(maxread == 0, NULL, 0);    /* quick rejection. */
 
-    if (avail < maxread)
-    {
-        maxread = avail - (avail % objSize);
-        objCount = (PHYSFS_uint32) (maxread / objSize);
-        BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0);  /* quick rejection. */
-        __PHYSFS_setError(ERR_PAST_EOF);   /* this is always true here. */
-    } /* if */
-
     if (entry->compression_method == COMPMETH_NONE)
-    {
-        retval = __PHYSFS_platformRead(finfo->handle, buf, objSize, objCount);
-    } /* if */
-
+        retval = __PHYSFS_platformRead(finfo->handle, buf, maxread);
     else
     {
         finfo->stream.next_out = buf;
-        finfo->stream.avail_out = objSize * objCount;
+        finfo->stream.avail_out = maxread;
 
         while (retval < maxread)
         {
@@ -241,9 +237,8 @@
                     if (br > ZIP_READBUFSIZE)
                         br = ZIP_READBUFSIZE;
 
-                    br = __PHYSFS_platformRead(finfo->handle,
-                                               finfo->buffer,
-                                               1, (PHYSFS_uint32) br);
+                    br = __PHYSFS_platformRead(finfo->handle, finfo->buffer,
+                                               (PHYSFS_uint64) br);
                     if (br <= 0)
                         break;
 
@@ -259,19 +254,16 @@
             if (rc != Z_OK)
                 break;
         } /* while */
-
-        retval /= objSize;
     } /* else */
 
     if (retval > 0)
-        finfo->uncompressed_position += (PHYSFS_uint32) (retval * objSize);
+        finfo->uncompressed_position += (PHYSFS_uint32) retval;
 
     return retval;
 } /* ZIP_read */
 
 
-static PHYSFS_sint64 ZIP_write(fvoid *opaque, const void *buf,
-                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+static PHYSFS_sint64 ZIP_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
 {
     BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
 } /* ZIP_write */
@@ -338,7 +330,7 @@
             if (maxread > sizeof (buf))
                 maxread = sizeof (buf);
 
-            if (ZIP_read(finfo, buf, maxread, 1) != 1)
+            if (ZIP_read(finfo, buf, maxread) != maxread)
                 return 0;
         } /* while */
     } /* else */
@@ -415,14 +407,14 @@
         /* make sure we catch a signature between buffers. */
         if (totalread != 0)
         {
-            if (__PHYSFS_platformRead(in, buf, maxread - 4, 1) != 1)
+            if (!readAll(in, buf, maxread - 4))
                 return -1;
             memcpy(&buf[maxread - 4], &extra, sizeof (extra));
             totalread += maxread - 4;
         } /* if */
         else
         {
-            if (__PHYSFS_platformRead(in, buf, maxread, 1) != 1)
+            if (!readAll(in, buf, maxread))
                 return -1;
             totalread += maxread;
         } /* else */
@@ -678,7 +670,7 @@
     BAIL_IF_MACRO(path == NULL, ERR_OUT_OF_MEMORY, 0);
     
     if (entry->compression_method == COMPMETH_NONE)
-        rc = (__PHYSFS_platformRead(in, path, size, 1) == 1);
+        rc = readAll(in, path, size);
 
     else  /* symlink target path is compressed... */
     {
@@ -687,7 +679,7 @@
         PHYSFS_uint8 *compressed = (PHYSFS_uint8*) __PHYSFS_smallAlloc(complen);
         if (compressed != NULL)
         {
-            if (__PHYSFS_platformRead(in, compressed, complen, 1) == 1)
+            if (readAll(in, compressed, complen))
             {
                 initializeZStream(&stream);
                 stream.next_in = compressed;
@@ -924,7 +916,7 @@
 
     entry->name = (char *) allocator.Malloc(fnamelen + 1);
     BAIL_IF_MACRO(entry->name == NULL, ERR_OUT_OF_MEMORY, 0);
-    if (__PHYSFS_platformRead(in, entry->name, fnamelen, 1) != 1)
+    if (!readAll(in, entry->name, fnamelen))
         goto zip_load_entry_puked;
 
     entry->name[fnamelen] = '\0';  /* null-terminate the filename. */
--- a/src/physfs.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/physfs.c	Sat Aug 21 02:47:58 2010 -0400
@@ -8,6 +8,8 @@
  *  This file written by Ryan C. Gordon.
  */
 
+/* !!! FIXME: ERR_PAST_EOF shouldn't trigger for reads. Just return zero. */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -1937,96 +1939,138 @@
 
 
 static PHYSFS_sint64 doBufferedRead(FileHandle *fh, void *buffer,
-                                    PHYSFS_uint32 objSize,
-                                    PHYSFS_uint32 objCount)
+                                    PHYSFS_uint64 len)
 {
     PHYSFS_sint64 retval = 0;
-    PHYSFS_uint32 remainder = 0;
-
-    while (objCount > 0)
+    PHYSFS_uint32 buffered = 0;
+    PHYSFS_sint64 rc = 0;
+
+    if (len == 0)
+        return 0;
+
+    buffered = fh->buffill - fh->bufpos;
+    if (buffered >= len)  /* totally in the buffer, just copy and return! */
     {
-        PHYSFS_uint32 buffered = fh->buffill - fh->bufpos;
-        PHYSFS_uint64 mustread = (objSize * objCount) - remainder;
-        PHYSFS_uint32 copied;
-
-        if (buffered == 0) /* need to refill buffer? */
-        {
-            PHYSFS_sint64 rc = fh->funcs->read(fh->opaque, fh->buffer,
-                                                1, fh->bufsize);
-            if (rc <= 0)
-            {
-                fh->bufpos -= remainder;
-                return ( ((rc == -1) && (retval == 0)) ? -1 : retval );
-            } /* if */
-
-            buffered = fh->buffill = (PHYSFS_uint32) rc;
-            fh->bufpos = 0;
-        } /* if */
-
-        if (buffered > mustread)
-            buffered = (PHYSFS_uint32) mustread;
-
+        memcpy(buffer, fh->buffer + fh->bufpos, (size_t) len);
+        fh->bufpos += (PHYSFS_uint32) len;
+        return (PHYSFS_sint64) len;
+    } /* else if */
+
+    if (buffered > 0) /* partially in the buffer... */
+    {
         memcpy(buffer, fh->buffer + fh->bufpos, (size_t) buffered);
         buffer = ((PHYSFS_uint8 *) buffer) + buffered;
-        fh->bufpos += buffered;
-        buffered += remainder;  /* take remainder into account. */
-        copied = (buffered / objSize);
-        remainder = (buffered % objSize);
-        retval += copied;
-        objCount -= copied;
-    } /* while */
-
-    return retval;
+        len -= buffered;
+        retval = buffered;
+        buffered = fh->buffill = fh->bufpos = 0;
+    } /* if */
+
+    /* if you got here, the buffer is drained and we still need bytes. */
+    assert(buffered == 0);
+    assert(len > 0);
+
+    if (len >= fh->bufsize)  /* need more than the buffer takes. */
+    {
+        /* leave buffer empty, go right to output instead. */
+        rc = fh->funcs->read(fh->opaque, buffer, len);
+        if (rc < 0)
+            return ((retval == 0) ? rc : retval);
+        return retval + rc;
+    } /* if */
+
+    /* need less than buffer can take. Fill buffer. */
+    rc = fh->funcs->read(fh->opaque, fh->buffer, fh->bufsize);
+    if (rc < 0)
+        return ((retval == 0) ? rc : retval);
+
+    assert(fh->bufpos == 0);
+    fh->buffill = (PHYSFS_uint32) rc;
+    rc = doBufferedRead(fh, buffer, len);  /* go from the start, again. */
+    if (rc < 0)
+        return ((retval == 0) ? rc : retval);
+
+    return retval + rc;
 } /* doBufferedRead */
 
 
 PHYSFS_sint64 PHYSFS_read(PHYSFS_File *handle, void *buffer,
-                          PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+                          PHYSFS_uint32 size, PHYSFS_uint32 count)
+{
+    const PHYSFS_uint64 len = ((PHYSFS_uint64) size) * ((PHYSFS_uint64) count);
+    const PHYSFS_sint64 retval = PHYSFS_readBytes(handle, buffer, len);
+    return ( (retval <= 0) ? retval : (retval / ((PHYSFS_sint64) count)) );
+} /* PHYSFS_read */
+
+
+PHYSFS_sint64 PHYSFS_readBytes(PHYSFS_File *handle, void *buffer,
+                               PHYSFS_uint64 len)
 {
     FileHandle *fh = (FileHandle *) handle;
 
+#ifdef PHYSFS_NO_64BIT_SUPPORT
+    const PHYSFS_uint64 maxlen = __PHYSFS_UI64(0x7FFFFFFF);
+#else
+    const PHYSFS_uint64 maxlen = __PHYSFS_UI64(0x7FFFFFFFFFFFFFFF);
+#endif
+
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
+    BAIL_IF_MACRO(len > maxlen, ERR_INVALID_ARGUMENT, -1);
     BAIL_IF_MACRO(!fh->forReading, ERR_FILE_ALREADY_OPEN_W, -1);
-    BAIL_IF_MACRO(objSize == 0, NULL, 0);
-    BAIL_IF_MACRO(objCount == 0, NULL, 0);
+    BAIL_IF_MACRO(len == 0, NULL, 0);
     if (fh->buffer != NULL)
-        return doBufferedRead(fh, buffer, objSize, objCount);
-
-    return fh->funcs->read(fh->opaque, buffer, objSize, objCount);
-} /* PHYSFS_read */
+        return doBufferedRead(fh, buffer, len);
+
+    return fh->funcs->read(fh->opaque, buffer, len);
+} /* PHYSFS_readBytes */
 
 
 static PHYSFS_sint64 doBufferedWrite(PHYSFS_File *handle, const void *buffer,
-                                     PHYSFS_uint32 objSize,
-                                     PHYSFS_uint32 objCount)
+                                     PHYSFS_uint64 len)
 {
     FileHandle *fh = (FileHandle *) handle;
 
     /* whole thing fits in the buffer? */
-    if (fh->buffill + (objSize * objCount) < fh->bufsize)
+    if ( (((PHYSFS_uint64) fh->buffill) + len) < fh->bufsize )
     {
-        memcpy(fh->buffer + fh->buffill, buffer, objSize * objCount);
-        fh->buffill += (objSize * objCount);
-        return objCount;
+        memcpy(fh->buffer + fh->buffill, buffer, (size_t) len);
+        fh->buffill += (PHYSFS_uint32) len;
+        return (PHYSFS_sint64) len;
     } /* if */
 
     /* would overflow buffer. Flush and then write the new objects, too. */
     BAIL_IF_MACRO(!PHYSFS_flush(handle), NULL, -1);
-    return fh->funcs->write(fh->opaque, buffer, objSize, objCount);
+    return fh->funcs->write(fh->opaque, buffer, len);
 } /* doBufferedWrite */
 
 
 PHYSFS_sint64 PHYSFS_write(PHYSFS_File *handle, const void *buffer,
-                           PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+                           PHYSFS_uint32 size, PHYSFS_uint32 count)
+{
+    const PHYSFS_uint64 len = ((PHYSFS_uint64) size) * ((PHYSFS_uint64) count);
+    const PHYSFS_sint64 retval = PHYSFS_writeBytes(handle, buffer, len);
+    return ( (retval <= 0) ? retval : (retval / ((PHYSFS_sint64) count)) );
+} /* PHYSFS_write */
+
+
+PHYSFS_sint64 PHYSFS_writeBytes(PHYSFS_File *handle, const void *buffer,
+                                PHYSFS_uint64 len)
 {
     FileHandle *fh = (FileHandle *) handle;
 
+#ifdef PHYSFS_NO_64BIT_SUPPORT
+    const PHYSFS_uint64 maxlen = __PHYSFS_UI64(0x7FFFFFFF);
+#else
+    const PHYSFS_uint64 maxlen = __PHYSFS_UI64(0x7FFFFFFFFFFFFFFF);
+#endif
+
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
+    BAIL_IF_MACRO(len > maxlen, ERR_INVALID_ARGUMENT, -1);
     BAIL_IF_MACRO(fh->forReading, ERR_FILE_ALREADY_OPEN_R, -1);
-    BAIL_IF_MACRO(objSize == 0, NULL, 0);
-    BAIL_IF_MACRO(objCount == 0, NULL, 0);
+    BAIL_IF_MACRO(len == 0, NULL, 0);
     if (fh->buffer != NULL)
-        return doBufferedWrite(handle, buffer, objSize, objCount);
-
-    return fh->funcs->write(fh->opaque, buffer, objSize, objCount);
+        return doBufferedWrite(handle, buffer, len);
+
+    return fh->funcs->write(fh->opaque, buffer, len);
 } /* PHYSFS_write */
 
 
@@ -2142,7 +2186,7 @@
 
     /* dump buffer to disk. */
     rc = fh->funcs->write(fh->opaque, fh->buffer + fh->bufpos,
-                          fh->buffill - fh->bufpos, 1);
+                          fh->buffill - fh->bufpos);
     BAIL_IF_MACRO(rc <= 0, NULL, 0);
     fh->bufpos = fh->buffill = 0;
     return 1;
--- a/src/physfs.h	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/physfs.h	Sat Aug 21 02:47:58 2010 -0400
@@ -1227,6 +1227,13 @@
  *
  * The file must be opened for reading.
  *
+ * \deprecated As of PhysicsFS 2.1, use PHYSFS_readBytes() instead. This
+ *             function just wraps it anyhow. This function never clarified
+ *             what would happen if you managed to read a partial object, so
+ *             working at the byte level makes this cleaner for everyone,
+ *             especially now that data streams can be supplied by the
+ *             application.
+ *
  *   \param handle handle returned from PHYSFS_openRead().
  *   \param buffer buffer to store read data into.
  *   \param objSize size in bytes of objects being read from (handle).
@@ -1235,6 +1242,7 @@
  *           the reason this might be < (objCount), as can PHYSFS_eof().
  *            -1 if complete failure.
  *
+ * \sa PHYSFS_readBytes
  * \sa PHYSFS_eof
  */
 PHYSFS_DECL PHYSFS_sint64 PHYSFS_read(PHYSFS_File *handle,
@@ -1248,12 +1256,21 @@
  *
  * The file must be opened for writing.
  *
+ * \deprecated As of PhysicsFS 2.1, use PHYSFS_writeBytes() instead. This
+ *             function just wraps it anyhow. This function never clarified
+ *             what would happen if you managed to write a partial object, so
+ *             working at the byte level makes this cleaner for everyone,
+ *             especially now that data streams can be supplied by the
+ *             application.
+ *
  *   \param handle retval from PHYSFS_openWrite() or PHYSFS_openAppend().
  *   \param buffer buffer of bytes to write to (handle).
  *   \param objSize size in bytes of objects being written to (handle).
  *   \param objCount number of (objSize) objects to write to (handle).
  *  \return number of objects written. PHYSFS_getLastError() can shed light on
  *           the reason this might be < (objCount). -1 if complete failure.
+ *
+ * \sa PHYSFS_writeBytes
  */
 PHYSFS_DECL PHYSFS_sint64 PHYSFS_write(PHYSFS_File *handle,
                                        const void *buffer,
@@ -2594,6 +2611,52 @@
                                     PHYSFS_uint64 len);
 
 
+/**
+ * \fn PHYSFS_sint64 PHYSFS_readBytes(PHYSFS_File *handle, void *buffer, PHYSFS_uint64 len)
+ * \brief Read bytes from a PhysicsFS filehandle
+ *
+ * The file must be opened for reading.
+ *
+ *   \param handle handle returned from PHYSFS_openRead().
+ *   \param buffer buffer of at least (len) bytes to store read data into.
+ *   \param len number of bytes being read from (handle).
+ *  \return number of bytes read. This may be less than (len); this does not
+ *          signify an error, necessarily (a short read may mean EOF).
+ *          PHYSFS_getLastError() can shed light on the reason this might
+ *          be < (len), as can PHYSFS_eof(). -1 if complete failure.
+ *
+ * \sa PHYSFS_eof
+ */
+PHYSFS_DECL PHYSFS_sint64 PHYSFS_readBytes(PHYSFS_File *handle, void *buffer,
+                                           PHYSFS_uint64 len);
+
+/**
+ * \fn PHYSFS_sint64 PHYSFS_write(PHYSFS_File *handle, const void *buffer, PHYSFS_uint64 len)
+ * \brief Write data to a PhysicsFS filehandle
+ *
+ * The file must be opened for writing.
+ *
+ * Please note that while (len) is an unsigned 64-bit integer, you are limited
+ *  to 63 bits (9223372036854775807 bytes), so we can return a negative value
+ *  on error. If length is greater than 0x7FFFFFFFFFFFFFFF, this function will
+ *  immediately fail. For systems without a 64-bit datatype, you are limited
+ *  to 31 bits (0x7FFFFFFF, or 2147483647 bytes). We trust most things won't
+ *  need to do multiple gigabytes of i/o in one call anyhow, but why limit
+ *  things?
+ *
+ *   \param handle retval from PHYSFS_openWrite() or PHYSFS_openAppend().
+ *   \param buffer buffer of (len) bytes to write to (handle).
+ *   \param len number of bytes being written to (handle).
+ *  \return number of bytes written. This may be less than (len); in the case
+ *          of an error, the system may try to write as many bytes as possible,
+ *          so an incomplete write might occur. PHYSFS_getLastError() can shed
+ *          light on the reason this might be < (len). -1 if complete failure.
+ */
+PHYSFS_DECL PHYSFS_sint64 PHYSFS_writeBytes(PHYSFS_File *handle,
+                                            const void *buffer,
+                                            PHYSFS_uint64 len);
+
+
 /* Everything above this line is part of the PhysicsFS 2.1 API. */
 
 
--- a/src/physfs_internal.h	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/physfs_internal.h	Sat Aug 21 02:47:58 2010 -0400
@@ -893,23 +893,19 @@
      */
 
         /*
-         * Read more from the file.
-         * Returns number of objects of (objSize) bytes read from file, -1
-         *  if complete failure.
+         * Read (len) bytes from the file.
+         * Returns number of bytes read from file, -1 if complete failure.
          * On failure, call __PHYSFS_setError().
          */
-    PHYSFS_sint64 (*read)(fvoid *opaque, void *buffer,
-                          PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+    PHYSFS_sint64 (*read)(fvoid *opaque, void *buffer, PHYSFS_uint64 len);
 
         /*
-         * Write more to the file. Archives don't have to implement this.
-         *  (Set it to NULL if not implemented).
-         * Returns number of objects of (objSize) bytes written to file, -1
-         *  if complete failure.
+         * Write (len) bytes to the file. Archives don't have to implement
+         *  this; set it to NULL if not implemented.
+         * Returns number of bytes written to file, -1 if complete failure.
          * On failure, call __PHYSFS_setError().
          */
-    PHYSFS_sint64 (*write)(fvoid *opaque, const void *buffer,
-                 PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
+    PHYSFS_sint64 (*write)(fvoid *opaque, const void *buf, PHYSFS_uint64 len);
 
         /*
          * Returns non-zero if at end of file.
@@ -1033,15 +1029,18 @@
 
 #define __PHYSFS_ARRAYLEN(x) ( (sizeof (x)) / (sizeof (x[0])) )
 
-#if (defined __GNUC__)
+#ifdef PHYSFS_NO_64BIT_SUPPORT
+#define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x))
+#define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x))
+#elif (defined __GNUC__)
 #define __PHYSFS_SI64(x) x##LL
 #define __PHYSFS_UI64(x) x##ULL
 #elif (defined _MSC_VER)
 #define __PHYSFS_SI64(x) x##i64
 #define __PHYSFS_UI64(x) x##ui64
 #else
-#define __PHYSFS_SI64(x) x
-#define __PHYSFS_UI64(x) x
+#define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x))
+#define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x))
 #endif
 
 
@@ -1192,30 +1191,32 @@
 
 /*
  * 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
+ *  cast to whatever data type your platform uses. Read a maximum of (len)
+ *  8-bit bytes to the area pointed to by (buf). If there isn't enough data
+ *  available, return the number of bytes read, and position the file pointer
+ *  immediately after those bytes.
+ *  On success, return (len) and position the file pointer immediately past
+ *  the end of the last read byte. 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.
+ *  pointer should not move in such a case. A partial read is success; only
+ *  return (-1) on total failure; presumably, the next read call after a
+ *  partial read will fail as such.
  */
-PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
-                                    PHYSFS_uint32 size, PHYSFS_uint32 count);
+PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len);
 
 /*
  * 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.
+ *  cast to whatever data type your platform uses. Write a maximum of (len)
+ *  8-bit bytes from the area pointed to by (buffer). If there is a problem,
+ *  return the number of bytes written, and position the file pointer
+ *  immediately after those bytes. 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. A partial write is success; only
+ *  return (-1) on total failure; presumably, the next write call after a
+ *  partial write will fail as such.
  */
 PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
-                                     PHYSFS_uint32 size, PHYSFS_uint32 count);
+                                     PHYSFS_uint64 len);
 
 /*
  * Set the file pointer to a new position. (opaque) should be cast to
--- a/src/platform_os2.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/platform_os2.c	Sat Aug 21 02:47:58 2010 -0400
@@ -517,49 +517,24 @@
 } /* __PHYSFS_platformOpenAppend */
 
 
-PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
-                                    PHYSFS_uint32 size, PHYSFS_uint32 count)
+PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len)
 {
-    HFILE hfile = (HFILE) opaque;
-    PHYSFS_sint64 retval;
-    ULONG br;
-
-    for (retval = 0; retval < count; retval++)
-    {
-        os2err(DosRead(hfile, buffer, size, &br));
-        if (br < size)
-        {
-            DosSetFilePtr(hfile, -br, FILE_CURRENT, &br); /* try to cleanup. */
-            return retval;
-        } /* if */
-
-        buffer = (void *) ( ((char *) buffer) + size );
-    } /* for */
-
-    return retval;
+    ULONG br = 0;
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
+    if (os2err(DosRead((HFILE) opaque, buf, (ULONG) len, &br)) != NO_ERROR)
+        return (br > 0) ? ((PHYSFS_sint64) br) : -1;
+    return (PHYSFS_sint64) br;
 } /* __PHYSFS_platformRead */
 
 
-PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
-                                     PHYSFS_uint32 size, PHYSFS_uint32 count)
+PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buf,
+                                     PHYSFS_uint64 len)
 {
-    HFILE hfile = (HFILE) opaque;
-    PHYSFS_sint64 retval;
-    ULONG bw;
-
-    for (retval = 0; retval < count; retval++)
-    {
-        os2err(DosWrite(hfile, buffer, size, &bw));
-        if (bw < size)
-        {
-            DosSetFilePtr(hfile, -bw, FILE_CURRENT, &bw); /* try to cleanup. */
-            return retval;
-        } /* if */
-
-        buffer = (void *) ( ((char *) buffer) + size );
-    } /* for */
-
-    return retval;
+    ULONG bw = 0;
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
+    if (os2err(DosWrite((HFILE) opaque, buf, (ULONG) len, &bw)) != NO_ERROR)
+        return (bw > 0) ? ((PHYSFS_sint64) bw) : -1;
+    return (PHYSFS_sint64) bw;
 } /* __PHYSFS_platformWrite */
 
 
--- a/src/platform_pocketpc.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/platform_pocketpc.c	Sat Aug 21 02:47:58 2010 -0400
@@ -382,53 +382,30 @@
 } /* __PHYSFS_platformOpenAppend */
 
 
-PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
-                                    PHYSFS_uint32 size, PHYSFS_uint32 count)
+PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len)
 {
     HANDLE Handle = ((winCEfile *) opaque)->handle;
-    DWORD CountOfBytesRead;
-    PHYSFS_sint64 retval;
+    DWORD CountOfBytesRead = 0;
+
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
 
-    /* Read data from the file */
-    /*!!! - uint32 might be a greater # than DWORD */
-    if (!ReadFile(Handle, buffer, count * size, &CountOfBytesRead, NULL))
-    {
-        retval = -1;
-    } /* if */
-    else
-    {
-        /* Return the number of "objects" read. */
-        /* !!! - What if not the right amount of bytes was read to make an object? */
-        retval = CountOfBytesRead / size;
-    } /* else */
-
-    return retval;
-
+    if (!ReadFile(Handle, buf, (DWORD) len, &CountOfBytesRead, NULL))
+        return -1;  /* !!! FIXME: set an error string? */
+    return (PHYSFS_sint64) CountOfBytesRead;
 } /* __PHYSFS_platformRead */
 
 
 PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
-                                     PHYSFS_uint32 size, PHYSFS_uint32 count)
+                                     PHYSFS_uint64 len)
 {
     HANDLE Handle = ((winCEfile *) opaque)->handle;
-    DWORD CountOfBytesWritten;
-    PHYSFS_sint64 retval;
+    DWORD CountOfBytesWritten = 0;
+
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
 
-    /* Read data from the file */
-    /*!!! - uint32 might be a greater # than DWORD */
-    if (!WriteFile(Handle, buffer, count * size, &CountOfBytesWritten, NULL))
-    {
-        retval = -1;
-    } /* if */
-    else
-    {
-        /* Return the number of "objects" read. */
-        /*!!! - What if not the right number of bytes was written? */
-        retval = CountOfBytesWritten / size;
-    } /* else */
-
-    return retval;
-
+    if (!WriteFile(Handle, buffer, (DWORD) len, &CountOfBytesWritten, NULL))
+        return -1;
+    return PHYSFS_sint64) CountOfBytesWritten;
 } /* __PHYSFS_platformWrite */
 
 
--- a/src/platform_posix.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/platform_posix.c	Sat Aug 21 02:47:58 2010 -0400
@@ -300,36 +300,34 @@
 
 
 PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
-                                    PHYSFS_uint32 size, PHYSFS_uint32 count)
+                                    PHYSFS_uint64 len)
 {
     int fd = *((int *) opaque);
-    int max = size * count;
-    int rc = read(fd, buffer, max);
+    ssize_t rc = 0;
+
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
 
-    BAIL_IF_MACRO(rc == -1, strerror(errno), rc);
-    assert(rc <= max);
-
-    if ((rc < max) && (size > 1))
-        lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */
-
-    return (rc / size);
+    rc = read(fd, buffer, (size_t) len);
+    BAIL_IF_MACRO(rc == -1, strerror(errno), (PHYSFS_sint64) rc);
+    assert(rc >= 0);
+    assert(rc <= len);
+    return (PHYSFS_sint64) rc;
 } /* __PHYSFS_platformRead */
 
 
 PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
-                                     PHYSFS_uint32 size, PHYSFS_uint32 count)
+                                     PHYSFS_uint64 len)
 {
     int fd = *((int *) opaque);
-    int max = size * count;
-    int rc = write(fd, (void *) buffer, max);
+    ssize_t rc = 0;
 
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
+
+    rc = write(fd, (void *) buffer, (size_t) len);
     BAIL_IF_MACRO(rc == -1, strerror(errno), rc);
-    assert(rc <= max);
-
-    if ((rc < max) && (size > 1))
-        lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */
-
-    return (rc / size);
+    assert(rc >= 0);
+    assert(rc <= len);
+    return (PHYSFS_sint64) rc;
 } /* __PHYSFS_platformWrite */
 
 
--- a/src/platform_windows.c	Sat Aug 21 02:42:23 2010 -0400
+++ b/src/platform_windows.c	Sat Aug 21 02:47:58 2010 -0400
@@ -1044,27 +1044,16 @@
 } /* __PHYSFS_platformOpenAppend */
 
 
-PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
-                                    PHYSFS_uint32 size, PHYSFS_uint32 count)
+PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len)
 {
     HANDLE Handle = ((WinApiFile *) opaque)->handle;
-    DWORD CountOfBytesRead;
-    PHYSFS_sint64 retval;
+    DWORD CountOfBytesRead = 0;
 
-    /* Read data from the file */
-    /* !!! FIXME: uint32 might be a greater # than DWORD */
-    if(!ReadFile(Handle, buffer, count * size, &CountOfBytesRead, NULL))
-    {
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
+
+    if(!ReadFile(Handle, buf, (DWORD) len, &CountOfBytesRead, NULL))
         BAIL_MACRO(winApiStrError(), -1);
-    } /* if */
-    else
-    {
-        /* Return the number of "objects" read. */
-        /* !!! FIXME: What if not the right amount of bytes was read to make an object? */
-        retval = CountOfBytesRead / size;
-    } /* else */
-
-    return retval;
+    return (PHYSFS_sint64) CountOfBytesRead;
 } /* __PHYSFS_platformRead */
 
 
@@ -1072,23 +1061,13 @@
                                      PHYSFS_uint32 size, PHYSFS_uint32 count)
 {
     HANDLE Handle = ((WinApiFile *) opaque)->handle;
-    DWORD CountOfBytesWritten;
-    PHYSFS_sint64 retval;
+    DWORD CountOfBytesWritten = 0;
 
-    /* Read data from the file */
-    /* !!! FIXME: uint32 might be a greater # than DWORD */
-    if(!WriteFile(Handle, buffer, count * size, &CountOfBytesWritten, NULL))
-    {
+    BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
+
+    if(!WriteFile(Handle, buffer, (DWORD) len, &CountOfBytesWritten, NULL))
         BAIL_MACRO(winApiStrError(), -1);
-    } /* if */
-    else
-    {
-        /* Return the number of "objects" read. */
-        /* !!! FIXME: What if not the right number of bytes was written? */
-        retval = CountOfBytesWritten / size;
-    } /* else */
-
-    return retval;
+    return (PHYSFS_sint64) CountOfBytesWritten;
 } /* __PHYSFS_platformWrite */