Added buffering API.
This commit is contained in:
parent
c1cf146a75
commit
3ad51e49e4
181
physfs.c
181
physfs.c
|
@ -1227,12 +1227,22 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
|
|||
if (h->funcs->isSymLink(h, str, &retval))
|
||||
{
|
||||
__PHYSFS_setError(ERR_SYMLINK_DISALLOWED);
|
||||
retval = 0;
|
||||
free(str);
|
||||
return(0); /* insecure. */
|
||||
} /* if */
|
||||
|
||||
/* break out early if path element is missing or it's a symlink. */
|
||||
/* break out early if path element is missing. */
|
||||
if (!retval)
|
||||
{
|
||||
/*
|
||||
* We need to clear it if it's the last element of the path,
|
||||
* since this might be a non-existant file we're opening
|
||||
* for writing...
|
||||
*/
|
||||
if (end == NULL)
|
||||
retval = 1;
|
||||
break;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
if (end == NULL)
|
||||
|
@ -1569,6 +1579,9 @@ static PHYSFS_file *doOpenWrite(const char *fname, int appending)
|
|||
free(list);
|
||||
else
|
||||
{
|
||||
rc->buffer = NULL; /* just in case. */
|
||||
rc->buffill = rc->bufpos = rc->bufsize = 0; /* just in case. */
|
||||
rc->forReading = 0;
|
||||
list->handle.opaque = (void *) rc;
|
||||
list->next = openWriteList;
|
||||
openWriteList = list;
|
||||
|
@ -1615,13 +1628,17 @@ PHYSFS_file *PHYSFS_openRead(const char *fname)
|
|||
BAIL_IF_MACRO_MUTEX(rc == NULL, NULL, stateLock, NULL);
|
||||
|
||||
list = (FileHandleList *) malloc(sizeof (FileHandleList));
|
||||
BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
|
||||
BAIL_IF_MACRO_MUTEX(!list, ERR_OUT_OF_MEMORY, stateLock, NULL);
|
||||
list->handle.opaque = (void *) rc;
|
||||
list->next = openReadList;
|
||||
openReadList = list;
|
||||
retval = &(list->handle);
|
||||
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
|
||||
rc->buffer = NULL; /* just in case. */
|
||||
rc->buffill = rc->bufpos = rc->bufsize = 0; /* just in case. */
|
||||
rc->forReading = 1;
|
||||
|
||||
return(retval);
|
||||
} /* PHYSFS_openRead */
|
||||
|
||||
|
@ -1631,16 +1648,22 @@ static int closeHandleInOpenList(FileHandleList **list, PHYSFS_file *handle)
|
|||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
FileHandleList *prev = NULL;
|
||||
FileHandleList *i;
|
||||
int rc;
|
||||
int rc = 1;
|
||||
|
||||
for (i = *list; i != NULL; i = i->next)
|
||||
{
|
||||
if (&i->handle == handle) /* handle is in this list? */
|
||||
{
|
||||
rc = h->funcs->fileClose(h);
|
||||
PHYSFS_uint8 *tmp = h->buffer;
|
||||
rc = PHYSFS_flush(handle);
|
||||
if (rc)
|
||||
rc = h->funcs->fileClose(h);
|
||||
if (!rc)
|
||||
return(-1);
|
||||
|
||||
if (tmp != NULL) /* free any associated buffer. */
|
||||
free(tmp);
|
||||
|
||||
if (prev == NULL)
|
||||
*list = i->next;
|
||||
else
|
||||
|
@ -1677,18 +1700,92 @@ int PHYSFS_close(PHYSFS_file *handle)
|
|||
} /* PHYSFS_close */
|
||||
|
||||
|
||||
static PHYSFS_sint64 doBufferedRead(PHYSFS_file *handle, void *buffer,
|
||||
PHYSFS_uint32 objSize,
|
||||
PHYSFS_uint32 objCount)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
PHYSFS_sint64 retval = 0;
|
||||
PHYSFS_uint32 remainder = 0;
|
||||
|
||||
while (objCount > 0)
|
||||
{
|
||||
PHYSFS_uint64 buffered = h->buffill - h->bufpos;
|
||||
PHYSFS_uint64 mustread = (objSize * objCount) - remainder;
|
||||
PHYSFS_uint32 copied;
|
||||
|
||||
if (buffered == 0) /* need to refill buffer? */
|
||||
{
|
||||
PHYSFS_sint64 rc = h->funcs->read(h, h->buffer, 1, h->bufsize);
|
||||
if (rc <= 0)
|
||||
{
|
||||
h->bufpos -= remainder;
|
||||
return(((rc == -1) && (retval == 0)) ? -1 : retval);
|
||||
} /* if */
|
||||
|
||||
buffered = h->buffill = rc;
|
||||
h->bufpos = 0;
|
||||
} /* if */
|
||||
|
||||
if (buffered > mustread)
|
||||
buffered = mustread;
|
||||
|
||||
memcpy(buffer, h->buffer + h->bufpos, (size_t) buffered);
|
||||
buffer = ((PHYSFS_uint8 *) buffer) + buffered;
|
||||
h->bufpos += buffered;
|
||||
buffered += remainder; /* take remainder into account. */
|
||||
copied = (buffered / objSize);
|
||||
remainder = (buffered % objSize);
|
||||
retval += copied;
|
||||
objCount -= copied;
|
||||
} /* while */
|
||||
|
||||
return(retval);
|
||||
} /* doBufferedRead */
|
||||
|
||||
|
||||
PHYSFS_sint64 PHYSFS_read(PHYSFS_file *handle, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
|
||||
BAIL_IF_MACRO(!h->forReading, ERR_FILE_ALREADY_OPEN_W, -1);
|
||||
if (h->buffer != NULL)
|
||||
return(doBufferedRead(handle, buffer, objSize, objCount));
|
||||
|
||||
return(h->funcs->read(h, buffer, objSize, objCount));
|
||||
} /* PHYSFS_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 doBufferedWrite(PHYSFS_file *handle, const void *buffer,
|
||||
PHYSFS_uint32 objSize,
|
||||
PHYSFS_uint32 objCount)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
|
||||
/* whole thing fits in the buffer? */
|
||||
if (h->buffill + (objSize * objCount) < h->bufsize)
|
||||
{
|
||||
memcpy(h->buffer + h->buffill, buffer, objSize * objCount);
|
||||
h->buffill += (objSize * objCount);
|
||||
return(objCount);
|
||||
} /* if */
|
||||
|
||||
/* would overflow buffer. Flush and then write the new objects, too. */
|
||||
BAIL_IF_MACRO(!PHYSFS_flush(handle), NULL, -1);
|
||||
return(h->funcs->write(h, buffer, objSize, objCount));
|
||||
} /* doBufferedWrite */
|
||||
|
||||
|
||||
PHYSFS_sint64 PHYSFS_write(PHYSFS_file *handle, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
|
||||
BAIL_IF_MACRO(h->forReading, ERR_FILE_ALREADY_OPEN_R, -1);
|
||||
if (h->buffer != NULL)
|
||||
return(doBufferedWrite(handle, buffer, objSize, objCount));
|
||||
|
||||
return(h->funcs->write(h, buffer, objSize, objCount));
|
||||
} /* PHYSFS_write */
|
||||
|
||||
|
@ -1696,20 +1793,29 @@ PHYSFS_sint64 PHYSFS_write(PHYSFS_file *handle, const void *buffer,
|
|||
int PHYSFS_eof(PHYSFS_file *handle)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
return(h->funcs->eof(h));
|
||||
|
||||
if (!h->forReading) /* never EOF on files opened for write/append. */
|
||||
return(0);
|
||||
|
||||
/* eof if buffer is empty and archiver says so. */
|
||||
return((h->bufpos == h->buffill) && (h->funcs->eof(h)));
|
||||
} /* PHYSFS_eof */
|
||||
|
||||
|
||||
PHYSFS_sint64 PHYSFS_tell(PHYSFS_file *handle)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
return(h->funcs->tell(h));
|
||||
PHYSFS_sint64 retval = h->forReading ?
|
||||
(h->funcs->tell(h) - h->buffill) + h->bufpos :
|
||||
(h->funcs->tell(h) + h->buffill);
|
||||
return(retval);
|
||||
} /* PHYSFS_tell */
|
||||
|
||||
|
||||
int PHYSFS_seek(PHYSFS_file *handle, PHYSFS_uint64 pos)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
BAIL_IF_MACRO(!PHYSFS_flush(handle), NULL, 0);
|
||||
return(h->funcs->seek(h, pos));
|
||||
} /* PHYSFS_seek */
|
||||
|
||||
|
@ -1721,6 +1827,65 @@ PHYSFS_sint64 PHYSFS_fileLength(PHYSFS_file *handle)
|
|||
} /* PHYSFS_filelength */
|
||||
|
||||
|
||||
int PHYSFS_setBuffer(PHYSFS_file *handle, PHYSFS_uint64 bufsize)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
|
||||
BAIL_IF_MACRO(!PHYSFS_flush(handle), NULL, 0);
|
||||
|
||||
/*
|
||||
* For reads, we need to move the file pointer to where it would be
|
||||
* if we weren't buffering, so that the next read will get the
|
||||
* right chunk of stuff from the file. PHYSFS_flush() handles writes.
|
||||
*/
|
||||
if ((h->forReading) && (h->buffill != h->bufpos))
|
||||
{
|
||||
PHYSFS_uint64 pos;
|
||||
PHYSFS_sint64 curpos = h->funcs->tell(h);
|
||||
BAIL_IF_MACRO(curpos == -1, NULL, 0);
|
||||
pos = ((curpos - h->buffill) + h->bufpos);
|
||||
BAIL_IF_MACRO(!h->funcs->seek(h, pos), NULL, 0);
|
||||
} /* if */
|
||||
|
||||
if (bufsize == 0) /* delete existing buffer. */
|
||||
{
|
||||
if (h->buffer != NULL)
|
||||
{
|
||||
free(h->buffer);
|
||||
h->buffer = NULL;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
else
|
||||
{
|
||||
PHYSFS_uint8 *newbuf = realloc(h->buffer, bufsize);
|
||||
BAIL_IF_MACRO(newbuf == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
h->buffer = newbuf;
|
||||
} /* else */
|
||||
|
||||
h->bufsize = bufsize;
|
||||
h->buffill = h->bufpos = 0;
|
||||
return(1);
|
||||
} /* PHYSFS_setBuffer */
|
||||
|
||||
|
||||
int PHYSFS_flush(PHYSFS_file *handle)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if ((h->forReading) || (h->bufpos == h->buffill))
|
||||
return(1); /* open for read or buffer empty are successful no-ops. */
|
||||
|
||||
/* dump buffer to disk. */
|
||||
rc = h->funcs->write(h, h->buffer + h->bufpos, h->buffill - h->bufpos, 1);
|
||||
BAIL_IF_MACRO(rc <= 0, NULL, 0);
|
||||
|
||||
h->bufpos = h->buffill = 0;
|
||||
return(1);
|
||||
} /* PHYSFS_flush */
|
||||
|
||||
|
||||
LinkedStringList *__PHYSFS_addToLinkedStringList(LinkedStringList *retval,
|
||||
LinkedStringList **prev,
|
||||
const char *str,
|
||||
|
|
110
physfs.h
110
physfs.h
|
@ -258,6 +258,8 @@ PHYSFS_COMPILE_TIME_ASSERT(sint64, sizeof(PHYSFS_sint64) == 8);
|
|||
* \sa PHYSFS_seek
|
||||
* \sa PHYSFS_tell
|
||||
* \sa PHYSFS_eof
|
||||
* \sa PHYSFS_setBuffer
|
||||
* \sa PHYSFS_flush
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
|
@ -289,6 +291,7 @@ typedef struct
|
|||
const char *url; /**< URL related to this archive */
|
||||
} PHYSFS_ArchiveInfo;
|
||||
|
||||
|
||||
/**
|
||||
* \struct PHYSFS_Version
|
||||
* \brief Information the version of PhysicsFS in use.
|
||||
|
@ -315,6 +318,9 @@ typedef struct
|
|||
#define PHYSFS_VER_PATCH 7
|
||||
#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
|
||||
|
||||
|
||||
/* PhysicsFS state stuff ... */
|
||||
|
||||
/**
|
||||
* \def PHYSFS_VERSION(x)
|
||||
* \brief Macro to determine PhysicsFS version program was compiled against.
|
||||
|
@ -775,6 +781,8 @@ __EXPORT__ int PHYSFS_setSaneConfig(const char *organization,
|
|||
int archivesFirst);
|
||||
|
||||
|
||||
/* Directory management stuff ... */
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_mkdir(const char *dirName)
|
||||
* \brief Create a directory.
|
||||
|
@ -856,7 +864,6 @@ __EXPORT__ int PHYSFS_delete(const char *filename);
|
|||
__EXPORT__ const char *PHYSFS_getRealDir(const char *filename);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \fn char **PHYSFS_enumerateFiles(const char *dir)
|
||||
* \brief Get a file listing of a search path's directory.
|
||||
|
@ -956,6 +963,24 @@ __EXPORT__ int PHYSFS_isDirectory(const char *fname);
|
|||
__EXPORT__ int PHYSFS_isSymbolicLink(const char *fname);
|
||||
|
||||
|
||||
/**
|
||||
* \fn PHYSFS_sint64 PHYSFS_getLastModTime(const char *filename)
|
||||
* \brief Get the last modification time of a file.
|
||||
*
|
||||
* The modtime is returned as a number of seconds since the epoch
|
||||
* (Jan 1, 1970). The exact derivation and accuracy of this time depends on
|
||||
* the particular archiver. If there is no reasonable way to obtain this
|
||||
* information for a particular archiver, or there was some sort of error,
|
||||
* this function returns (-1).
|
||||
*
|
||||
* \param filename filename to check, in platform-independent notation.
|
||||
* \return last modified time of the file. -1 if it can't be determined.
|
||||
*/
|
||||
__EXPORT__ PHYSFS_sint64 PHYSFS_getLastModTime(const char *filename);
|
||||
|
||||
|
||||
/* i/o stuff... */
|
||||
|
||||
/**
|
||||
* \fn PHYSFS_file *PHYSFS_openWrite(const char *filename)
|
||||
* \brief Open a file for writing.
|
||||
|
@ -1053,22 +1078,6 @@ __EXPORT__ PHYSFS_file *PHYSFS_openRead(const char *filename);
|
|||
__EXPORT__ int PHYSFS_close(PHYSFS_file *handle);
|
||||
|
||||
|
||||
/**
|
||||
* \fn PHYSFS_sint64 PHYSFS_getLastModTime(const char *filename)
|
||||
* \brief Get the last modification time of a file.
|
||||
*
|
||||
* The modtime is returned as a number of seconds since the epoch
|
||||
* (Jan 1, 1970). The exact derivation and accuracy of this time depends on
|
||||
* the particular archiver. If there is no reasonable way to obtain this
|
||||
* information for a particular archiver, or there was some sort of error,
|
||||
* this function returns (-1).
|
||||
*
|
||||
* \param filename filename to check, in platform-independent notation.
|
||||
* \return last modified time of the file. -1 if it can't be determined.
|
||||
*/
|
||||
__EXPORT__ PHYSFS_sint64 PHYSFS_getLastModTime(const char *filename);
|
||||
|
||||
|
||||
/**
|
||||
* \fn PHYSFS_sint64 PHYSFS_read(PHYSFS_file *handle, void *buffer, PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
* \brief Read data from a PhysicsFS filehandle
|
||||
|
@ -1108,6 +1117,9 @@ __EXPORT__ PHYSFS_sint64 PHYSFS_write(PHYSFS_file *handle,
|
|||
PHYSFS_uint32 objSize,
|
||||
PHYSFS_uint32 objCount);
|
||||
|
||||
|
||||
/* File position stuff... */
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_eof(PHYSFS_file *handle)
|
||||
* \brief Check for end-of-file state on a PhysicsFS filehandle.
|
||||
|
@ -1172,6 +1184,70 @@ __EXPORT__ int PHYSFS_seek(PHYSFS_file *handle, PHYSFS_uint64 pos);
|
|||
__EXPORT__ PHYSFS_sint64 PHYSFS_fileLength(PHYSFS_file *handle);
|
||||
|
||||
|
||||
/* Buffering stuff... */
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_setBuffer(PHYSFS_file *handle, PHYSFS_uint64 bufsize)
|
||||
* \brief Set up buffering for a PhysicsFS file handle.
|
||||
*
|
||||
* Define an i/o buffer for a file handle. A memory block of (bufsize) bytes
|
||||
* will be allocated and associated with (handle).
|
||||
*
|
||||
* For files opened for reading, up to (bufsize) bytes are read from (handle)
|
||||
* and stored in the internal buffer. Calls to PHYSFS_read() will pull
|
||||
* from this buffer until it is empty, and then refill it for more reading.
|
||||
* Note that compressed files, like ZIP archives, will decompress while
|
||||
* buffering, so this can be handy for offsetting CPU-intensive operations.
|
||||
* The buffer isn't filled until you do your next read.
|
||||
*
|
||||
* For files opened for writing, data will be buffered to memory until the
|
||||
* buffer is full or the buffer is flushed. Closing a handle implicitly
|
||||
* causes a flush...check your return values!
|
||||
*
|
||||
* Seeking, etc transparently accounts for buffering.
|
||||
*
|
||||
* You can resize an existing buffer by calling this function more than once
|
||||
* on the same file. Setting the buffer size to zero will free an existing
|
||||
* buffer.
|
||||
*
|
||||
* PhysicsFS file handles are unbuffered by default.
|
||||
*
|
||||
* Please check the return value of this function! Failures can include
|
||||
* not being able to seek backwards in a read-only file when removing the
|
||||
* buffer, not being able to allocate the buffer, and not being able to
|
||||
* flush the buffer to disk, among other unexpected problems.
|
||||
*
|
||||
* \param handle handle returned from PHYSFS_open*().
|
||||
* \param bufsize size, in bytes, of buffer to allocate.
|
||||
* \return nonzero if successful, zero on error.
|
||||
*
|
||||
* \sa PHYSFS_flush
|
||||
* \sa PHYSFS_read
|
||||
* \sa PHYSFS_write
|
||||
* \sa PHYSFS_close
|
||||
*/
|
||||
__EXPORT__ int PHYSFS_setBuffer(PHYSFS_file *handle, PHYSFS_uint64 bufsize);
|
||||
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_flush(PHYSFS_file *handle, PHYSFS_uint64 bufsize)
|
||||
* \brief Flush a buffered PhysicsFS file handle.
|
||||
*
|
||||
* For buffered files opened for writing, this will put the current contents
|
||||
* of the buffer to disk and flag the buffer as empty if possible.
|
||||
*
|
||||
* For buffered files opened for reading or unbuffered files, this is a safe
|
||||
* no-op, and will report success.
|
||||
*
|
||||
* \param handle handle returned from PHYSFS_open*().
|
||||
* \return nonzero if successful, zero on error.
|
||||
*
|
||||
* \sa PHYSFS_setBuffer
|
||||
* \sa PHYSFS_close
|
||||
*/
|
||||
__EXPORT__ int PHYSFS_flush(PHYSFS_file *handle);
|
||||
|
||||
|
||||
/* Byteorder stuff... */
|
||||
|
||||
/**
|
||||
|
|
|
@ -724,6 +724,31 @@ typedef struct __PHYSFS_FILEHANDLE__
|
|||
*/
|
||||
void *opaque;
|
||||
|
||||
/*
|
||||
* Non-zero if file opened for reading, zero if write/append.
|
||||
*/
|
||||
PHYSFS_uint8 forReading;
|
||||
|
||||
/*
|
||||
* This is the buffer, if one is set (NULL otherwise). Don't touch.
|
||||
*/
|
||||
PHYSFS_uint8 *buffer;
|
||||
|
||||
/*
|
||||
* This is the buffer size, if one is set (0 otherwise). Don't touch.
|
||||
*/
|
||||
PHYSFS_uint64 bufsize;
|
||||
|
||||
/*
|
||||
* This is the buffer fill size. Don't touch.
|
||||
*/
|
||||
PHYSFS_uint64 buffill;
|
||||
|
||||
/*
|
||||
* This is the buffer position. Don't touch.
|
||||
*/
|
||||
PHYSFS_uint64 bufpos;
|
||||
|
||||
/*
|
||||
* This should be the DirHandle that created this FileHandle.
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#define TEST_VERSION_PATCH 7
|
||||
|
||||
static FILE *history_file = NULL;
|
||||
static PHYSFS_uint32 do_buffer_size = 0;
|
||||
|
||||
static void output_versions(void)
|
||||
{
|
||||
|
@ -288,6 +289,230 @@ static int cmd_permitsyms(char *args)
|
|||
} /* cmd_permitsyms */
|
||||
|
||||
|
||||
static int cmd_setbuffer(char *args)
|
||||
{
|
||||
if (*args == '\"')
|
||||
{
|
||||
args++;
|
||||
args[strlen(args) - 1] = '\0';
|
||||
} /* if */
|
||||
|
||||
do_buffer_size = atoi(args);
|
||||
if (do_buffer_size)
|
||||
{
|
||||
printf("Further tests will set a (%lu) size buffer.\n",
|
||||
(unsigned long) do_buffer_size);
|
||||
} /* if */
|
||||
|
||||
else
|
||||
{
|
||||
printf("Further tests will NOT use a buffer.\n");
|
||||
} /* else */
|
||||
|
||||
return(1);
|
||||
} /* cmd_setbuffer */
|
||||
|
||||
|
||||
static int cmd_stressbuffer(char *args)
|
||||
{
|
||||
int num;
|
||||
|
||||
if (*args == '\"')
|
||||
{
|
||||
args++;
|
||||
args[strlen(args) - 1] = '\0';
|
||||
} /* if */
|
||||
|
||||
num = atoi(args);
|
||||
if (num < 0)
|
||||
printf("buffer must be greater than or equal to zero.\n");
|
||||
else
|
||||
{
|
||||
PHYSFS_file *f;
|
||||
int rndnum;
|
||||
|
||||
printf("Stress testing with (%d) byte buffer...\n", num);
|
||||
f = PHYSFS_openWrite("test.txt");
|
||||
if (f == NULL)
|
||||
printf("Couldn't open test.txt for writing: %s.\n", PHYSFS_getLastError());
|
||||
else
|
||||
{
|
||||
int i, j;
|
||||
char buf[37];
|
||||
char buf2[37];
|
||||
|
||||
if (!PHYSFS_setBuffer(f, num))
|
||||
{
|
||||
printf("PHYSFS_setBuffer() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
PHYSFS_delete("test.txt");
|
||||
return(1);
|
||||
} /* if */
|
||||
|
||||
strcpy(buf, "abcdefghijklmnopqrstuvwxyz0123456789");
|
||||
srand(time(NULL));
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
for (j = 0; j < 10000; j++)
|
||||
{
|
||||
int right = 1 + (int) (35.0 * rand() / (RAND_MAX + 1.0));
|
||||
int left = 36 - right;
|
||||
if (PHYSFS_write(f, buf, left, 1) != 1)
|
||||
{
|
||||
printf("PHYSFS_write() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
|
||||
rndnum = 1 + (int) (1000.0 * rand() / (RAND_MAX + 1.0));
|
||||
if (rndnum == 42)
|
||||
{
|
||||
if (!PHYSFS_flush(f))
|
||||
{
|
||||
printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
if (PHYSFS_write(f, buf + left, 1, right) != right)
|
||||
{
|
||||
printf("PHYSFS_write() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
|
||||
rndnum = 1 + (int) (1000.0 * rand() / (RAND_MAX + 1.0));
|
||||
if (rndnum == 42)
|
||||
{
|
||||
if (!PHYSFS_flush(f))
|
||||
{
|
||||
printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
if (!PHYSFS_flush(f))
|
||||
{
|
||||
printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
|
||||
} /* for */
|
||||
|
||||
if (!PHYSFS_close(f))
|
||||
{
|
||||
printf("PHYSFS_close() failed: %s.\n", PHYSFS_getLastError());
|
||||
return(1); /* oh well. */
|
||||
} /* if */
|
||||
|
||||
printf(" ... test file written ...\n");
|
||||
f = PHYSFS_openRead("test.txt");
|
||||
if (f == NULL)
|
||||
{
|
||||
printf("Failed to reopen stress file for reading: %s.\n", PHYSFS_getLastError());
|
||||
return(1);
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_setBuffer(f, num))
|
||||
{
|
||||
printf("PHYSFS_setBuffer() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
for (j = 0; j < 10000; j++)
|
||||
{
|
||||
int right = 1 + (int) (35.0 * rand() / (RAND_MAX + 1.0));
|
||||
int left = 36 - right;
|
||||
if (PHYSFS_read(f, buf2, left, 1) != 1)
|
||||
{
|
||||
printf("PHYSFS_read() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
|
||||
rndnum = 1 + (int) (1000.0 * rand() / (RAND_MAX + 1.0));
|
||||
if (rndnum == 42)
|
||||
{
|
||||
if (!PHYSFS_flush(f))
|
||||
{
|
||||
printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
if (PHYSFS_read(f, buf2 + left, 1, right) != right)
|
||||
{
|
||||
printf("PHYSFS_read() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
|
||||
rndnum = 1 + (int) (1000.0 * rand() / (RAND_MAX + 1.0));
|
||||
if (rndnum == 42)
|
||||
{
|
||||
if (!PHYSFS_flush(f))
|
||||
{
|
||||
printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
if (memcmp(buf, buf2, 36) != 0)
|
||||
{
|
||||
printf("readback is mismatched on iterations (%d, %d).\n", i, j);
|
||||
printf("wanted: [");
|
||||
for (i = 0; i < 36; i++)
|
||||
printf("%c", buf[i]);
|
||||
printf("]\n");
|
||||
|
||||
printf(" got: [");
|
||||
for (i = 0; i < 36; i++)
|
||||
printf("%c", buf2[i]);
|
||||
printf("]\n");
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
if (!PHYSFS_flush(f))
|
||||
{
|
||||
printf("PHYSFS_flush() failed: %s.\n", PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
|
||||
} /* for */
|
||||
|
||||
printf(" ... test file read ...\n");
|
||||
|
||||
if (!PHYSFS_eof(f))
|
||||
printf("PHYSFS_eof() returned true! That's wrong.\n");
|
||||
|
||||
if (!PHYSFS_close(f))
|
||||
{
|
||||
printf("PHYSFS_close() failed: %s.\n", PHYSFS_getLastError());
|
||||
return(1); /* oh well. */
|
||||
} /* if */
|
||||
|
||||
PHYSFS_delete("test.txt");
|
||||
printf("stress test completed successfully.\n");
|
||||
} /* else */
|
||||
} /* else */
|
||||
|
||||
return(1);
|
||||
} /* cmd_stressbuffer */
|
||||
|
||||
|
||||
static int cmd_setsaneconfig(char *args)
|
||||
{
|
||||
char *org;
|
||||
|
@ -433,6 +658,17 @@ static int cmd_cat(char *args)
|
|||
printf("failed to open. Reason: [%s].\n", PHYSFS_getLastError());
|
||||
else
|
||||
{
|
||||
if (do_buffer_size)
|
||||
{
|
||||
if (!PHYSFS_setBuffer(f, do_buffer_size))
|
||||
{
|
||||
printf("failed to set file buffer. Reason: [%s].\n",
|
||||
PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
while (1)
|
||||
{
|
||||
char buffer[128];
|
||||
|
@ -506,8 +742,22 @@ static int cmd_append(char *args)
|
|||
printf("failed to open. Reason: [%s].\n", PHYSFS_getLastError());
|
||||
else
|
||||
{
|
||||
size_t bw = strlen(WRITESTR);
|
||||
PHYSFS_sint64 rc = PHYSFS_write(f, WRITESTR, 1, bw);
|
||||
size_t bw;
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (do_buffer_size)
|
||||
{
|
||||
if (!PHYSFS_setBuffer(f, do_buffer_size))
|
||||
{
|
||||
printf("failed to set file buffer. Reason: [%s].\n",
|
||||
PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
bw = strlen(WRITESTR);
|
||||
rc = PHYSFS_write(f, WRITESTR, 1, bw);
|
||||
if (rc != bw)
|
||||
{
|
||||
printf("Wrote (%d) of (%d) bytes. Reason: [%s].\n",
|
||||
|
@ -540,8 +790,22 @@ static int cmd_write(char *args)
|
|||
printf("failed to open. Reason: [%s].\n", PHYSFS_getLastError());
|
||||
else
|
||||
{
|
||||
size_t bw = strlen(WRITESTR);
|
||||
PHYSFS_sint64 rc = PHYSFS_write(f, WRITESTR, 1, bw);
|
||||
size_t bw;
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (do_buffer_size)
|
||||
{
|
||||
if (!PHYSFS_setBuffer(f, do_buffer_size))
|
||||
{
|
||||
printf("failed to set file buffer. Reason: [%s].\n",
|
||||
PHYSFS_getLastError());
|
||||
PHYSFS_close(f);
|
||||
return(1);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
bw = strlen(WRITESTR);
|
||||
rc = PHYSFS_write(f, WRITESTR, 1, bw);
|
||||
if (rc != bw)
|
||||
{
|
||||
printf("Wrote (%d) of (%d) bytes. Reason: [%s].\n",
|
||||
|
@ -648,6 +912,8 @@ static const command_info commands[] =
|
|||
{ "append", cmd_append, 1, "<fileToAppend>" },
|
||||
{ "write", cmd_write, 1, "<fileToCreateOrTrash>" },
|
||||
{ "getlastmodtime", cmd_getlastmodtime, 1, "<fileToExamine>" },
|
||||
{ "setbuffer", cmd_setbuffer, 1, "<bufferSize>" },
|
||||
{ "stressbuffer", cmd_stressbuffer, 1, "<bufferSize>" },
|
||||
{ NULL, NULL, -1, NULL }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue