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