mirror of
https://github.com/libretro/RetroArch
synced 2025-04-10 06:44:27 +00:00
Rewrite file_stream.c - reimplement filestream_error
This commit is contained in:
parent
4dfbfc4d02
commit
d12df0d91f
@ -84,6 +84,8 @@
|
|||||||
#include <retro_miscellaneous.h>
|
#include <retro_miscellaneous.h>
|
||||||
#include <encodings/utf.h>
|
#include <encodings/utf.h>
|
||||||
|
|
||||||
|
static const int64_t vfs_error_return_value = -1;
|
||||||
|
|
||||||
retro_vfs_file_get_path_t filestream_get_path_cb = NULL;
|
retro_vfs_file_get_path_t filestream_get_path_cb = NULL;
|
||||||
retro_vfs_file_open_t filestream_open_cb = NULL;
|
retro_vfs_file_open_t filestream_open_cb = NULL;
|
||||||
retro_vfs_file_close_t filestream_close_cb = NULL;
|
retro_vfs_file_close_t filestream_close_cb = NULL;
|
||||||
@ -95,12 +97,6 @@ retro_vfs_file_write_t filestream_write_cb = NULL;
|
|||||||
retro_vfs_file_flush_t filestream_flush_cb = NULL;
|
retro_vfs_file_flush_t filestream_flush_cb = NULL;
|
||||||
retro_vfs_file_delete_t filestream_delete_cb = NULL;
|
retro_vfs_file_delete_t filestream_delete_cb = NULL;
|
||||||
|
|
||||||
struct RFILE
|
|
||||||
{
|
|
||||||
unsigned hints;
|
|
||||||
int64_t size;
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
#if !defined(_WIN32) || defined(LEGACY_WIN32)
|
#if !defined(_WIN32) || defined(LEGACY_WIN32)
|
||||||
#define MODE_STR_READ "r"
|
#define MODE_STR_READ "r"
|
||||||
#define MODE_STR_READ_UNBUF "rb"
|
#define MODE_STR_READ_UNBUF "rb"
|
||||||
@ -113,13 +109,21 @@ struct RFILE
|
|||||||
#define MODE_STR_WRITE_PLUS L"w+"
|
#define MODE_STR_WRITE_PLUS L"w+"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct RFILE
|
||||||
|
{
|
||||||
|
bool error_flag;
|
||||||
|
int fd;
|
||||||
|
unsigned hints;
|
||||||
|
int64_t size;
|
||||||
#if defined(HAVE_MMAP)
|
#if defined(HAVE_MMAP)
|
||||||
uint8_t *mapped;
|
|
||||||
uint64_t mappos;
|
uint64_t mappos;
|
||||||
uint64_t mapsize;
|
uint64_t mapsize;
|
||||||
#endif
|
#endif
|
||||||
int fd;
|
|
||||||
char *buf;
|
char *buf;
|
||||||
|
FILE *fp;
|
||||||
|
#if defined(HAVE_MMAP)
|
||||||
|
uint8_t *mapped;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* VFS Initialization */
|
/* VFS Initialization */
|
||||||
@ -141,7 +145,8 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
|||||||
|
|
||||||
vfs_iface = vfs_info->iface;
|
vfs_iface = vfs_info->iface;
|
||||||
|
|
||||||
if (vfs_info->required_interface_version < FILESTREAM_REQUIRED_VFS_VERSION || vfs_iface == NULL)
|
if (vfs_info->required_interface_version <
|
||||||
|
FILESTREAM_REQUIRED_VFS_VERSION || !vfs_iface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
filestream_get_path_cb = vfs_iface->file_get_path;
|
filestream_get_path_cb = vfs_iface->file_get_path;
|
||||||
@ -158,13 +163,101 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
|||||||
|
|
||||||
/* Callback wrappers */
|
/* Callback wrappers */
|
||||||
|
|
||||||
int64_t filestream_get_size(RFILE *stream)
|
static int64_t filestream_file_size_impl(RFILE *stream)
|
||||||
{
|
{
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return 0;
|
return 0;
|
||||||
return stream->size;
|
return stream->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t filestream_seek_impl(
|
||||||
|
RFILE *stream, ssize_t offset, int whence)
|
||||||
|
{
|
||||||
|
if (!stream)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
|
return fseek(stream->fp, (long)offset, whence);
|
||||||
|
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
/* Need to check stream->mapped because this function is
|
||||||
|
* called in filestream_open() */
|
||||||
|
if (stream->mapped && stream->hints &
|
||||||
|
RETRO_VFS_FILE_ACCESS_HINT_MEMORY_MAP)
|
||||||
|
{
|
||||||
|
/* fseek() returns error on under/overflow but
|
||||||
|
* allows cursor > EOF for
|
||||||
|
read-only file descriptors. */
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
if (offset < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
stream->mappos = offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_CUR:
|
||||||
|
if ((offset < 0 && stream->mappos + offset > stream->mappos) ||
|
||||||
|
(offset > 0 && stream->mappos + offset < stream->mappos))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
stream->mappos += offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_END:
|
||||||
|
if (stream->mapsize + offset < stream->mapsize)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
stream->mappos = stream->mapsize + offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return stream->mappos;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (lseek(stream->fd, offset, whence) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t filestream_tell_impl(RFILE *stream)
|
||||||
|
{
|
||||||
|
if (!stream)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
|
return ftell(stream->fp);
|
||||||
|
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
/* Need to check stream->mapped because this function
|
||||||
|
* is called in filestream_open() */
|
||||||
|
if (stream->mapped && stream->hints & RETRO_VFS_FILE_ACCESS_HINT_MEMORY_MAP)
|
||||||
|
return stream->mappos;
|
||||||
|
#endif
|
||||||
|
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t filestream_get_size(RFILE *stream)
|
||||||
|
{
|
||||||
|
int64_t output = filestream_file_size_impl(stream);
|
||||||
|
|
||||||
|
if (output == vfs_error_return_value)
|
||||||
|
stream->error_flag = true;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
static void filestream_set_size(RFILE *stream)
|
static void filestream_set_size(RFILE *stream)
|
||||||
{
|
{
|
||||||
filestream_seek(stream, 0, SEEK_SET);
|
filestream_seek(stream, 0, SEEK_SET);
|
||||||
@ -362,56 +455,15 @@ int filestream_getc(RFILE *stream)
|
|||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence)
|
ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence)
|
||||||
{
|
{
|
||||||
if (!stream)
|
int64_t output = filestream_seek_impl(stream, offset, whence);
|
||||||
goto error;
|
|
||||||
|
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if (output == vfs_error_return_value)
|
||||||
return fseek(stream->fp, (long)offset, whence);
|
stream->error_flag = true;
|
||||||
|
|
||||||
#ifdef HAVE_MMAP
|
return output;
|
||||||
/* Need to check stream->mapped because this function is
|
|
||||||
* called in filestream_open() */
|
|
||||||
if (stream->mapped && stream->hints & RETRO_VFS_FILE_ACCESS_HINT_MEMORY_MAP)
|
|
||||||
{
|
|
||||||
/* fseek() returns error on under/overflow but allows cursor > EOF for
|
|
||||||
read-only file descriptors. */
|
|
||||||
switch (whence)
|
|
||||||
{
|
|
||||||
case SEEK_SET:
|
|
||||||
if (offset < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
stream->mappos = offset;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SEEK_CUR:
|
|
||||||
if ((offset < 0 && stream->mappos + offset > stream->mappos) ||
|
|
||||||
(offset > 0 && stream->mappos + offset < stream->mappos))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
stream->mappos += offset;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SEEK_END:
|
|
||||||
if (stream->mapsize + offset < stream->mapsize)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
stream->mappos = stream->mapsize + offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return stream->mappos;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (lseek(stream->fd, offset, whence) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int filestream_eof(RFILE *stream)
|
int filestream_eof(RFILE *stream)
|
||||||
@ -424,35 +476,26 @@ int filestream_eof(RFILE *stream)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t filestream_tell(RFILE *stream)
|
ssize_t filestream_tell(RFILE *stream)
|
||||||
{
|
{
|
||||||
if (!stream)
|
ssize_t output = filestream_tell_impl(stream);
|
||||||
goto error;
|
|
||||||
|
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if (output == vfs_error_return_value)
|
||||||
return ftell(stream->fp);
|
stream->error_flag = true;
|
||||||
|
|
||||||
#ifdef HAVE_MMAP
|
return output;
|
||||||
/* Need to check stream->mapped because this function
|
|
||||||
* is called in filestream_open() */
|
|
||||||
if (stream->mapped && stream->hints & RETRO_VFS_FILE_ACCESS_HINT_MEMORY_MAP)
|
|
||||||
return stream->mappos;
|
|
||||||
#endif
|
|
||||||
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void filestream_rewind(RFILE *stream)
|
void filestream_rewind(RFILE *stream)
|
||||||
{
|
{
|
||||||
|
if (!stream)
|
||||||
|
return;
|
||||||
filestream_seek(stream, 0L, SEEK_SET);
|
filestream_seek(stream, 0L, SEEK_SET);
|
||||||
|
stream->error_flag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t filestream_read(RFILE *stream, void *s, size_t len)
|
static ssize_t filestream_read_impl(RFILE *stream, void *s, size_t len)
|
||||||
{
|
{
|
||||||
if (!stream || !s)
|
if (!stream || !s)
|
||||||
goto error;
|
goto error;
|
||||||
@ -482,9 +525,31 @@ error:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t filestream_read(RFILE *stream, void *s, size_t len)
|
||||||
|
{
|
||||||
|
int64_t output = filestream_read_impl(stream, s, len);
|
||||||
|
|
||||||
|
if (output == vfs_error_return_value)
|
||||||
|
stream->error_flag = true;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int filestream_flush_impl(RFILE *stream)
|
||||||
|
{
|
||||||
|
if (!stream)
|
||||||
|
return -1;
|
||||||
|
return fflush(stream->fp);
|
||||||
|
}
|
||||||
|
|
||||||
int filestream_flush(RFILE *stream)
|
int filestream_flush(RFILE *stream)
|
||||||
{
|
{
|
||||||
return fflush(stream->fp);
|
int output = filestream_flush_impl(stream);
|
||||||
|
|
||||||
|
if (output == vfs_error_return_value)
|
||||||
|
stream->error_flag = true;
|
||||||
|
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t filestream_write(RFILE *stream, const void *s, size_t len)
|
ssize_t filestream_write(RFILE *stream, const void *s, size_t len)
|
||||||
@ -538,7 +603,9 @@ int filestream_printf(RFILE *stream, const char* format, ...)
|
|||||||
|
|
||||||
int filestream_error(RFILE *stream)
|
int filestream_error(RFILE *stream)
|
||||||
{
|
{
|
||||||
return ferror(stream->fp);
|
if (stream->error_flag)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int filestream_close(RFILE *stream)
|
int filestream_close(RFILE *stream)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user