From 4000b234c0ca87bdb83bd06aac73ec6fff1b57a2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 21 Aug 2010 02:47:58 -0400 Subject: [PATCH] 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 | 14 ++-- src/archiver_grp.c | 38 +++++------ src/archiver_hog.c | 50 ++++++-------- src/archiver_iso9660.c | 67 ++++++++----------- src/archiver_lzma.c | 29 +++----- src/archiver_mvl.c | 27 ++++---- src/archiver_qpak.c | 50 ++++++-------- src/archiver_wad.c | 47 ++++++------- src/archiver_zip.c | 56 +++++++--------- src/physfs.c | 144 ++++++++++++++++++++++++++-------------- src/physfs.h | 63 ++++++++++++++++++ src/physfs_internal.h | 63 +++++++++--------- src/platform_os2.c | 51 ++++---------- src/platform_pocketpc.c | 47 ++++--------- src/platform_posix.c | 34 +++++----- src/platform_windows.c | 43 +++--------- 16 files changed, 401 insertions(+), 422 deletions(-) diff --git a/src/archiver_dir.c b/src/archiver_dir.c index 097bea37..99d6640a 100644 --- a/src/archiver_dir.c +++ b/src/archiver_dir.c @@ -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 */ diff --git a/src/archiver_grp.c b/src/archiver_grp.c index dff943ea..9f4b1c8c 100644 --- a/src/archiver_grp.c +++ b/src/archiver_grp.c @@ -57,6 +57,12 @@ typedef struct } 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 @@ static void GRP_dirClose(dvoid *opaque) } /* 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 @@ static int grp_open(const char *filename, int forWriting, *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 @@ static int grp_open(const char *filename, int forWriting, 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 @@ static int grp_load_entries(const char *name, int forWriting, GRPinfo *info) 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 @@ static int grp_load_entries(const char *name, int forWriting, GRPinfo *info) 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; diff --git a/src/archiver_hog.c b/src/archiver_hog.c index def68c2b..9b700132 100644 --- a/src/archiver_hog.c +++ b/src/archiver_hog.c @@ -71,6 +71,12 @@ typedef struct } 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 @@ static void HOG_dirClose(dvoid *opaque) } /* 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 @@ static int hog_open(const char *filename, int forWriting, *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 @@ static int hog_open(const char *filename, int forWriting, 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 @@ static int hog_load_entries(const char *name, int forWriting, HOGinfo *info) 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 @@ static int hog_load_entries(const char *name, int forWriting, HOGinfo *info) entry->size = PHYSFS_swapULE32(entry->size); entry->startPos = (unsigned int) __PHYSFS_platformTell(fh); - if (entry->startPos == -1) - { - __PHYSFS_platformClose(fh); - return 0; - } /* Skip over entry */ - if (!__PHYSFS_platformSeek(fh, entry->startPos + entry->size)) + if ( (entry->startPos == -1) || + (!__PHYSFS_platformSeek(fh, entry->startPos + entry->size)) ) { __PHYSFS_platformClose(fh); return 0; - } + } /* if */ } /* for */ __PHYSFS_platformClose(fh); diff --git a/src/archiver_iso9660.c b/src/archiver_iso9660.c index a02670a0..c38f21d3 100644 --- a/src/archiver_iso9660.c +++ b/src/archiver_iso9660.c @@ -217,7 +217,7 @@ typedef struct __ISO9660FileHandle 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_extractfilename(ISO9660Handle *handle, ******************************************************************************/ 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 @@ static int iso_readimage(ISO9660Handle *handle, PHYSFS_uint64 where, 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 @@ static PHYSFS_sint64 iso_readfiledescriptor(ISO9660Handle *handle, 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 @@ static PHYSFS_sint64 iso_readfiledescriptor(ISO9660Handle *handle, 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 @@ static int iso_read_ext_attributes(ISO9660Handle *handle, int block, ISO9660ExtAttributeRec *attributes) { return iso_readimage(handle, block * 2048, attributes, - sizeof(ISO9660ExtAttributeRec), 1); + sizeof(ISO9660ExtAttributeRec)); } /* iso_read_ext_attributes */ @@ -502,7 +501,7 @@ static int ISO9660_isArchive(const char *filename, int forWriting) } /* 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 @@ static void *ISO9660_openArchive(const char *filename, int forWriting) 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 void ISO9660_dirClose(dvoid *opaque) 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 int iso_file_close_mem(ISO9660FileHandle *fhandle) 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 @@ static int iso_file_open_mem(ISO9660Handle *handle, ISO9660FileHandle *fhandle) 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 @@ static int ISO9660_fileClose(fvoid *opaque) 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 @@ static int ISO9660_mkdir(dvoid *opaque, const char *name) } /* 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 */ diff --git a/src/archiver_lzma.c b/src/archiver_lzma.c index fcfefbba..b93f32d9 100644 --- a/src/archiver_lzma.c +++ b/src/archiver_lzma.c @@ -113,7 +113,7 @@ SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxReqSize, 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 @@ SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, 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 @@ static int lzma_err(SZ_RESULT rc) } /* 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 @@ static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer, 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 @@ static int LZMA_isArchive(const char *filename, int forWriting) 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); diff --git a/src/archiver_mvl.c b/src/archiver_mvl.c index 9584117b..a71643e6 100644 --- a/src/archiver_mvl.c +++ b/src/archiver_mvl.c @@ -69,28 +69,25 @@ static void MVL_dirClose(dvoid *opaque) } /* 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 @@ static int mvl_open(const char *filename, int forWriting, *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 @@ static int mvl_open(const char *filename, int forWriting, 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 @@ static int mvl_load_entries(const char *name, int forWriting, MVLinfo *info) 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; diff --git a/src/archiver_qpak.c b/src/archiver_qpak.c index 82b3584c..47d0c656 100644 --- a/src/archiver_qpak.c +++ b/src/archiver_qpak.c @@ -83,28 +83,25 @@ static void QPAK_dirClose(dvoid *opaque) } /* 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 @@ static int QPAK_fileClose(fvoid *opaque) } /* 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 @@ static int qpak_open(const char *filename, int forWriting, *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 @@ static int qpak_load_entries(const char *name, int forWriting, QPAKinfo *info) 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); diff --git a/src/archiver_wad.c b/src/archiver_wad.c index 68f58d18..b58b8fc6 100644 --- a/src/archiver_wad.c +++ b/src/archiver_wad.c @@ -85,28 +85,25 @@ static void WAD_dirClose(dvoid *opaque) } /* 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 @@ static int WAD_fileClose(fvoid *opaque) } /* 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 @@ static int wad_open(const char *filename, int forWriting, *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 @@ static int wad_open(const char *filename, int forWriting, 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 @@ static int wad_load_entries(const char *name, int forWriting, WADinfo *info) 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; diff --git a/src/archiver_zip.c b/src/archiver_zip.c index a0b22bf0..675a841e 100644 --- a/src/archiver_zip.c +++ b/src/archiver_zip.c @@ -172,13 +172,18 @@ static int zlib_err(int rc) } /* 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 readui32(void *in, PHYSFS_uint32 *val) 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; - 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 */ + maxread = avail; - if (entry->compression_method == COMPMETH_NONE) - { - retval = __PHYSFS_platformRead(finfo->handle, buf, objSize, objCount); - } /* if */ + BAIL_IF_MACRO(maxread == 0, NULL, 0); /* quick rejection. */ + if (entry->compression_method == COMPMETH_NONE) + 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 @@ static PHYSFS_sint64 ZIP_read(fvoid *opaque, void *buf, 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 @@ static PHYSFS_sint64 ZIP_read(fvoid *opaque, void *buf, 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 @@ static int ZIP_seek(fvoid *opaque, PHYSFS_uint64 offset) 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 @@ static PHYSFS_sint64 zip_find_end_of_central_dir(void *in, PHYSFS_sint64 *len) /* 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 @@ static int zip_resolve_symlink(void *in, ZIPinfo *info, ZIPentry *entry) 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 @@ static int zip_resolve_symlink(void *in, ZIPinfo *info, ZIPentry *entry) 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 @@ static int zip_load_entry(void *in, ZIPentry *entry, PHYSFS_uint32 ofs_fixup) 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. */ diff --git a/src/physfs.c b/src/physfs.c index b1b9cfd6..19877962 100644 --- a/src/physfs.c +++ b/src/physfs.c @@ -8,6 +8,8 @@ * This file written by Ryan C. Gordon. */ +/* !!! FIXME: ERR_PAST_EOF shouldn't trigger for reads. Just return zero. */ + #include #include #include @@ -1937,96 +1939,138 @@ int PHYSFS_close(PHYSFS_File *_handle) 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; + PHYSFS_uint32 buffered = 0; + PHYSFS_sint64 rc = 0; + + if (len == 0) + return 0; - while (objCount > 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; + memcpy(buffer, fh->buffer + fh->bufpos, (size_t) len); + fh->bufpos += (PHYSFS_uint32) len; + return (PHYSFS_sint64) len; + } /* else if */ - 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 */ + if (buffered > 0) /* partially in the buffer... */ + { + memcpy(buffer, fh->buffer + fh->bufpos, (size_t) buffered); + buffer = ((PHYSFS_uint8 *) buffer) + buffered; + len -= buffered; + retval = buffered; + buffered = fh->buffill = fh->bufpos = 0; + } /* if */ - buffered = fh->buffill = (PHYSFS_uint32) rc; - fh->bufpos = 0; - } /* if */ + /* if you got here, the buffer is drained and we still need bytes. */ + assert(buffered == 0); + assert(len > 0); - if (buffered > mustread) - buffered = (PHYSFS_uint32) mustread; + 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 */ - 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 */ + /* 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); - return 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 doBufferedRead(fh, buffer, len); - return fh->funcs->read(fh->opaque, buffer, objSize, objCount); -} /* PHYSFS_read */ + 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 doBufferedWrite(handle, buffer, len); - return fh->funcs->write(fh->opaque, buffer, objSize, objCount); + return fh->funcs->write(fh->opaque, buffer, len); } /* PHYSFS_write */ @@ -2142,7 +2186,7 @@ int PHYSFS_flush(PHYSFS_File *handle) /* 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; diff --git a/src/physfs.h b/src/physfs.h index 44ea89cb..adf543b1 100644 --- a/src/physfs.h +++ b/src/physfs.h @@ -1227,6 +1227,13 @@ PHYSFS_DECL int PHYSFS_close(PHYSFS_File *handle); * * 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 @@ PHYSFS_DECL int PHYSFS_close(PHYSFS_File *handle); * 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 @@ PHYSFS_DECL PHYSFS_sint64 PHYSFS_read(PHYSFS_File *handle, * * 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_DECL void PHYSFS_utf8ToUtf16(const char *src, PHYSFS_uint16 *dst, 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. */ diff --git a/src/physfs_internal.h b/src/physfs_internal.h index c42b1318..865a7045 100644 --- a/src/physfs_internal.h +++ b/src/physfs_internal.h @@ -893,23 +893,19 @@ typedef struct */ /* - * 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 @@ void __PHYSFS_sort(void *entries, PHYSFS_uint32 max, #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 @@ 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 + * 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 diff --git a/src/platform_os2.c b/src/platform_os2.c index 22627389..303471df 100644 --- a/src/platform_os2.c +++ b/src/platform_os2.c @@ -517,49 +517,24 @@ void *__PHYSFS_platformOpenAppend(const char *_filename) } /* __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 */ diff --git a/src/platform_pocketpc.c b/src/platform_pocketpc.c index 6a1a2eb4..a874cb44 100644 --- a/src/platform_pocketpc.c +++ b/src/platform_pocketpc.c @@ -382,53 +382,30 @@ void *__PHYSFS_platformOpenAppend(const char *filename) } /* __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; - - /* 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 */ + DWORD CountOfBytesRead = 0; - return retval; + BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1); + 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; - - /* 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 */ + DWORD CountOfBytesWritten = 0; - return retval; + BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1); + if (!WriteFile(Handle, buffer, (DWORD) len, &CountOfBytesWritten, NULL)) + return -1; + return PHYSFS_sint64) CountOfBytesWritten; } /* __PHYSFS_platformWrite */ diff --git a/src/platform_posix.c b/src/platform_posix.c index 10e3f7a9..56a6a2e6 100644 --- a/src/platform_posix.c +++ b/src/platform_posix.c @@ -300,36 +300,34 @@ void *__PHYSFS_platformOpenAppend(const char *filename) 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(rc == -1, strerror(errno), rc); - assert(rc <= max); - - if ((rc < max) && (size > 1)) - lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */ + BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1); - 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(rc == -1, strerror(errno), rc); - assert(rc <= max); + BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1); - if ((rc < max) && (size > 1)) - lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */ - - return (rc / size); + rc = write(fd, (void *) buffer, (size_t) len); + BAIL_IF_MACRO(rc == -1, strerror(errno), rc); + assert(rc >= 0); + assert(rc <= len); + return (PHYSFS_sint64) rc; } /* __PHYSFS_platformWrite */ diff --git a/src/platform_windows.c b/src/platform_windows.c index 24f7bb0a..6a0a1953 100644 --- a/src/platform_windows.c +++ b/src/platform_windows.c @@ -1044,27 +1044,16 @@ void *__PHYSFS_platformOpenAppend(const char *filename) } /* __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_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 */ + BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1); - return retval; + if(!ReadFile(Handle, buf, (DWORD) len, &CountOfBytesRead, NULL)) + BAIL_MACRO(winApiStrError(), -1); + return (PHYSFS_sint64) CountOfBytesRead; } /* __PHYSFS_platformRead */ @@ -1072,23 +1061,13 @@ PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer, 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_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 */ + BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1); - return retval; + if(!WriteFile(Handle, buffer, (DWORD) len, &CountOfBytesWritten, NULL)) + BAIL_MACRO(winApiStrError(), -1); + return (PHYSFS_sint64) CountOfBytesWritten; } /* __PHYSFS_platformWrite */