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 <lists/string_list.h>
|
||||||
#include <string/stdstring.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(
|
static int file_archive_get_file_list_cb(
|
||||||
const char *path,
|
const char *path,
|
||||||
const char *valid_exts,
|
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);
|
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_current = 0;
|
||||||
state->step_total = 0;
|
state->step_total = 0;
|
||||||
|
|
||||||
|
@ -273,6 +300,16 @@ int file_archive_parse_file_iterate(
|
||||||
state->archive_file = NULL;
|
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)
|
if (userdata)
|
||||||
userdata->transfer = NULL;
|
userdata->transfer = NULL;
|
||||||
break;
|
break;
|
||||||
|
@ -306,6 +343,10 @@ static bool file_archive_walk(const char *file, const char *valid_exts,
|
||||||
|
|
||||||
state.type = ARCHIVE_TRANSFER_INIT;
|
state.type = ARCHIVE_TRANSFER_INIT;
|
||||||
state.archive_file = NULL;
|
state.archive_file = NULL;
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
state.archive_mmap_fd = 0;
|
||||||
|
state.archive_mmap_data = NULL;
|
||||||
|
#endif
|
||||||
state.archive_size = 0;
|
state.archive_size = 0;
|
||||||
state.context = NULL;
|
state.context = NULL;
|
||||||
state.step_total = 0;
|
state.step_total = 0;
|
||||||
|
@ -642,6 +683,10 @@ uint32_t file_archive_get_file_crc32(const char *path)
|
||||||
|
|
||||||
state.type = ARCHIVE_TRANSFER_INIT;
|
state.type = ARCHIVE_TRANSFER_INIT;
|
||||||
state.archive_file = NULL;
|
state.archive_file = NULL;
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
state.archive_mmap_fd = 0;
|
||||||
|
state.archive_mmap_data = NULL;
|
||||||
|
#endif
|
||||||
state.archive_size = 0;
|
state.archive_size = 0;
|
||||||
state.context = NULL;
|
state.context = NULL;
|
||||||
state.step_total = 0;
|
state.step_total = 0;
|
||||||
|
|
|
@ -49,7 +49,7 @@ enum file_archive_compression_mode
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
RFILE *file;
|
struct file_archive_transfer *state;
|
||||||
uint8_t *directory;
|
uint8_t *directory;
|
||||||
uint8_t *directory_entry;
|
uint8_t *directory_entry;
|
||||||
uint8_t *directory_end;
|
uint8_t *directory_end;
|
||||||
|
@ -79,10 +79,15 @@ static void zip_context_free_stream(
|
||||||
zip_context->current_stream = NULL;
|
zip_context->current_stream = NULL;
|
||||||
}
|
}
|
||||||
if (zip_context->compressed_data)
|
if (zip_context->compressed_data)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
if (!zip_context->state->archive_mmap_data)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
free(zip_context->compressed_data);
|
free(zip_context->compressed_data);
|
||||||
zip_context->compressed_data = NULL;
|
zip_context->compressed_data = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (zip_context->decompressed_data && !keep_decompressed)
|
if (zip_context->decompressed_data && !keep_decompressed)
|
||||||
{
|
{
|
||||||
free(zip_context->decompressed_data);
|
free(zip_context->decompressed_data);
|
||||||
|
@ -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)
|
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size)
|
||||||
{
|
{
|
||||||
zip_context_t *zip_context = (zip_context_t *)context;
|
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_buf[4];
|
||||||
|
uint8_t *local_header;
|
||||||
uint32_t offsetNL, offsetEL;
|
uint32_t offsetNL, offsetEL;
|
||||||
int64_t offsetData;
|
int64_t offsetData;
|
||||||
|
|
||||||
/* free previous stream if left unfinished */
|
/* free previous data and stream if left unfinished */
|
||||||
zip_context_free_stream(zip_context, false);
|
zip_context_free_stream(zip_context, false);
|
||||||
|
|
||||||
|
/* seek past most of the local directory header */
|
||||||
|
#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, 2); /* file name length */
|
||||||
|
offsetEL = read_le(local_header + 2, 2); /* extra field length */
|
||||||
|
offsetData = (int64_t)(size_t)cdata + 26 + 4 + offsetNL + offsetEL;
|
||||||
|
|
||||||
|
#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 */
|
/* allocate memory for the compressed data */
|
||||||
zip_context->compressed_data = (uint8_t*)malloc(csize);
|
zip_context->compressed_data = (uint8_t*)malloc(csize);
|
||||||
if (!zip_context->compressed_data)
|
if (!zip_context->compressed_data)
|
||||||
goto error;
|
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;
|
|
||||||
|
|
||||||
offsetNL = read_le(local_header_buf, 2); /* file name length */
|
|
||||||
offsetEL = read_le(local_header_buf + 2, 2); /* extra field length */
|
|
||||||
offsetData = (int64_t)(size_t)cdata + 26 + 4 + offsetNL + offsetEL;
|
|
||||||
|
|
||||||
/* skip over name and extra data */
|
/* skip over name and extra data */
|
||||||
filestream_seek(zip_context->file, offsetData, RETRO_VFS_SEEK_POSITION_START);
|
filestream_seek(state->archive_file, offsetData, RETRO_VFS_SEEK_POSITION_START);
|
||||||
if (filestream_read(zip_context->file, zip_context->compressed_data, csize) != csize)
|
if (filestream_read(state->archive_file, zip_context->compressed_data, csize) != csize)
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
switch (cmode)
|
switch (cmode)
|
||||||
{
|
{
|
||||||
case ZIP_MODE_STORED:
|
case ZIP_MODE_STORED:
|
||||||
zip_context->decompressed_data = zip_context->compressed_data;
|
handle->data = zip_context->compressed_data;
|
||||||
zip_context->compressed_data = NULL;
|
|
||||||
handle->data = zip_context->decompressed_data;
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case ZIP_MODE_DEFLATED:
|
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.
|
* 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 = (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 = (uint8_t*)(zip_context + 1);
|
||||||
zip_context->directory_entry = zip_context->directory;
|
zip_context->directory_entry = zip_context->directory;
|
||||||
zip_context->directory_end = zip_context->directory + (size_t)directory_size;
|
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;
|
enum file_archive_transfer_type type;
|
||||||
struct RFILE *archive_file;
|
struct RFILE *archive_file;
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
int archive_mmap_fd;
|
||||||
|
uint8_t *archive_mmap_data;
|
||||||
|
#endif
|
||||||
int64_t archive_size;
|
int64_t archive_size;
|
||||||
void *context;
|
void *context;
|
||||||
unsigned step_total, step_current;
|
unsigned step_total, step_current;
|
||||||
|
|
Loading…
Reference in New Issue