mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-24 08:30:16 +00:00
Bring back MMAP support
Will be used where available for files up to 256MB
This commit is contained in:
parent
c05f1e91fc
commit
32dcff3880
@ -32,6 +32,14 @@
|
||||
#include <lists/string_list.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
static int file_archive_get_file_list_cb(
|
||||
const char *path,
|
||||
const char *valid_exts,
|
||||
@ -159,6 +167,25 @@ static int file_archive_parse_file_init(file_archive_transfer_t *state,
|
||||
|
||||
state->archive_size = filestream_get_size(state->archive_file);
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
if (state->archive_size <= (256*1024*1024))
|
||||
{
|
||||
state->archive_mmap_fd = open(path, O_RDONLY);
|
||||
if (state->archive_mmap_fd)
|
||||
{
|
||||
state->archive_mmap_data = (uint8_t*)mmap(NULL, (size_t)state->archive_size,
|
||||
PROT_READ, MAP_SHARED, state->archive_mmap_fd, 0);
|
||||
|
||||
if (state->archive_mmap_data == (uint8_t*)MAP_FAILED)
|
||||
{
|
||||
close(state->archive_mmap_fd);
|
||||
state->archive_mmap_fd = 0;
|
||||
state->archive_mmap_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
state->step_current = 0;
|
||||
state->step_total = 0;
|
||||
|
||||
@ -273,6 +300,16 @@ int file_archive_parse_file_iterate(
|
||||
state->archive_file = NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
if (state->archive_mmap_data)
|
||||
{
|
||||
munmap(state->archive_mmap_data, (size_t)state->archive_size);
|
||||
close(state->archive_mmap_fd);
|
||||
state->archive_mmap_fd = 0;
|
||||
state->archive_mmap_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (userdata)
|
||||
userdata->transfer = NULL;
|
||||
break;
|
||||
@ -302,15 +339,19 @@ static bool file_archive_walk(const char *file, const char *valid_exts,
|
||||
file_archive_file_cb file_cb, struct archive_extract_userdata *userdata)
|
||||
{
|
||||
file_archive_transfer_t state;
|
||||
bool returnerr = true;
|
||||
bool returnerr = true;
|
||||
|
||||
state.type = ARCHIVE_TRANSFER_INIT;
|
||||
state.archive_file = NULL;
|
||||
state.archive_size = 0;
|
||||
state.context = NULL;
|
||||
state.step_total = 0;
|
||||
state.step_current = 0;
|
||||
state.backend = NULL;
|
||||
state.type = ARCHIVE_TRANSFER_INIT;
|
||||
state.archive_file = NULL;
|
||||
#ifdef HAVE_MMAP
|
||||
state.archive_mmap_fd = 0;
|
||||
state.archive_mmap_data = NULL;
|
||||
#endif
|
||||
state.archive_size = 0;
|
||||
state.context = NULL;
|
||||
state.step_total = 0;
|
||||
state.step_current = 0;
|
||||
state.backend = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -640,13 +681,17 @@ uint32_t file_archive_get_file_crc32(const char *path)
|
||||
archive_path += 1;
|
||||
}
|
||||
|
||||
state.type = ARCHIVE_TRANSFER_INIT;
|
||||
state.archive_file = NULL;
|
||||
state.archive_size = 0;
|
||||
state.context = NULL;
|
||||
state.step_total = 0;
|
||||
state.step_current = 0;
|
||||
state.backend = NULL;
|
||||
state.type = ARCHIVE_TRANSFER_INIT;
|
||||
state.archive_file = NULL;
|
||||
#ifdef HAVE_MMAP
|
||||
state.archive_mmap_fd = 0;
|
||||
state.archive_mmap_data = NULL;
|
||||
#endif
|
||||
state.archive_size = 0;
|
||||
state.context = NULL;
|
||||
state.step_total = 0;
|
||||
state.step_current = 0;
|
||||
state.backend = NULL;
|
||||
|
||||
/* Initialize and open archive first.
|
||||
Sets next state type to ITERATE. */
|
||||
|
@ -49,7 +49,7 @@ enum file_archive_compression_mode
|
||||
|
||||
typedef struct
|
||||
{
|
||||
RFILE *file;
|
||||
struct file_archive_transfer *state;
|
||||
uint8_t *directory;
|
||||
uint8_t *directory_entry;
|
||||
uint8_t *directory_end;
|
||||
@ -80,8 +80,13 @@ static void zip_context_free_stream(
|
||||
}
|
||||
if (zip_context->compressed_data)
|
||||
{
|
||||
free(zip_context->compressed_data);
|
||||
zip_context->compressed_data = NULL;
|
||||
#ifdef HAVE_MMAP
|
||||
if (!zip_context->state->archive_mmap_data)
|
||||
#endif
|
||||
{
|
||||
free(zip_context->compressed_data);
|
||||
zip_context->compressed_data = NULL;
|
||||
}
|
||||
}
|
||||
if (zip_context->decompressed_data && !keep_decompressed)
|
||||
{
|
||||
@ -95,38 +100,57 @@ static bool zlib_stream_decompress_data_to_file_init(
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size)
|
||||
{
|
||||
zip_context_t *zip_context = (zip_context_t *)context;
|
||||
struct file_archive_transfer *state = zip_context->state;
|
||||
uint8_t local_header_buf[4];
|
||||
uint8_t *local_header;
|
||||
uint32_t offsetNL, offsetEL;
|
||||
int64_t offsetData;
|
||||
|
||||
/* free previous stream if left unfinished */
|
||||
/* free previous data and stream if left unfinished */
|
||||
zip_context_free_stream(zip_context, false);
|
||||
|
||||
/* allocate memory for the compressed data */
|
||||
zip_context->compressed_data = (uint8_t*)malloc(csize);
|
||||
if (!zip_context->compressed_data)
|
||||
goto error;
|
||||
|
||||
/* seek past most of the local directory header */
|
||||
filestream_seek(zip_context->file, (int64_t)(size_t)cdata + 26, RETRO_VFS_SEEK_POSITION_START);
|
||||
if (filestream_read(zip_context->file, local_header_buf, 4) != 4)
|
||||
goto error;
|
||||
#ifdef HAVE_MMAP
|
||||
if (state->archive_mmap_data)
|
||||
{
|
||||
local_header = state->archive_mmap_data + (size_t)cdata + 26;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
filestream_seek(state->archive_file, (int64_t)(size_t)cdata + 26, RETRO_VFS_SEEK_POSITION_START);
|
||||
if (filestream_read(state->archive_file, local_header_buf, 4) != 4)
|
||||
goto error;
|
||||
local_header = local_header_buf;
|
||||
}
|
||||
|
||||
offsetNL = read_le(local_header_buf, 2); /* file name length */
|
||||
offsetEL = read_le(local_header_buf + 2, 2); /* extra field length */
|
||||
offsetNL = read_le(local_header, 2); /* file name length */
|
||||
offsetEL = read_le(local_header + 2, 2); /* extra field length */
|
||||
offsetData = (int64_t)(size_t)cdata + 26 + 4 + offsetNL + offsetEL;
|
||||
|
||||
/* skip over name and extra data */
|
||||
filestream_seek(zip_context->file, offsetData, RETRO_VFS_SEEK_POSITION_START);
|
||||
if (filestream_read(zip_context->file, zip_context->compressed_data, csize) != csize)
|
||||
goto error;
|
||||
#ifdef HAVE_MMAP
|
||||
if (state->archive_mmap_data)
|
||||
{
|
||||
zip_context->compressed_data = state->archive_mmap_data + (size_t)offsetData;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* allocate memory for the compressed data */
|
||||
zip_context->compressed_data = (uint8_t*)malloc(csize);
|
||||
if (!zip_context->compressed_data)
|
||||
goto error;
|
||||
|
||||
/* skip over name and extra data */
|
||||
filestream_seek(state->archive_file, offsetData, RETRO_VFS_SEEK_POSITION_START);
|
||||
if (filestream_read(state->archive_file, zip_context->compressed_data, csize) != csize)
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (cmode)
|
||||
{
|
||||
case ZIP_MODE_STORED:
|
||||
zip_context->decompressed_data = zip_context->compressed_data;
|
||||
zip_context->compressed_data = NULL;
|
||||
handle->data = zip_context->decompressed_data;
|
||||
handle->data = zip_context->compressed_data;
|
||||
return true;
|
||||
|
||||
case ZIP_MODE_DEFLATED:
|
||||
@ -397,7 +421,7 @@ static int zip_parse_file_init(file_archive_transfer_t *state,
|
||||
* context and the entire directory, then read the directory.
|
||||
*/
|
||||
zip_context = (zip_context_t*)malloc(sizeof(zip_context_t) + (size_t)directory_size);
|
||||
zip_context->file = state->archive_file;
|
||||
zip_context->state = state;
|
||||
zip_context->directory = (uint8_t*)(zip_context + 1);
|
||||
zip_context->directory_entry = zip_context->directory;
|
||||
zip_context->directory_end = zip_context->directory + (size_t)directory_size;
|
||||
|
@ -58,6 +58,10 @@ typedef struct file_archive_transfer
|
||||
{
|
||||
enum file_archive_transfer_type type;
|
||||
struct RFILE *archive_file;
|
||||
#ifdef HAVE_MMAP
|
||||
int archive_mmap_fd;
|
||||
uint8_t *archive_mmap_data;
|
||||
#endif
|
||||
int64_t archive_size;
|
||||
void *context;
|
||||
unsigned step_total, step_current;
|
||||
|
Loading…
Reference in New Issue
Block a user