mirror of
https://github.com/libretro/RetroArch
synced 2025-04-16 08:43:10 +00:00
Included direct to file extraction into 7z and zip format readers. They are used in case of need_fullpath and archive usage
This commit is contained in:
parent
adfa00e193
commit
097eb15721
@ -30,7 +30,10 @@
|
|||||||
#include "../deps/7zip/7zFile.h"
|
#include "../deps/7zip/7zFile.h"
|
||||||
#include "../deps/7zip/7zVersion.h"
|
#include "../deps/7zip/7zVersion.h"
|
||||||
|
|
||||||
|
/* Undefined at the end of the file
|
||||||
|
* Don't use outside of this file
|
||||||
|
*/
|
||||||
|
#define RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX 16384
|
||||||
|
|
||||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||||
|
|
||||||
@ -164,9 +167,11 @@ static SRes ConvertUtf16toCharString(const UInt16 *s, char *outstring)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Extract the relative path relative_path from a 7z archive
|
/* Extract the relative path relative_path from a 7z archive
|
||||||
* archive_path and allocate a buf for it to write it in. */
|
* archive_path and allocate a buf for it to write it in.
|
||||||
|
* If optional_outfile is set, extract to that instead and don't alloc buffer.
|
||||||
|
*/
|
||||||
int read_7zip_file(const char * archive_path,
|
int read_7zip_file(const char * archive_path,
|
||||||
const char *relative_path, void **buf)
|
const char *relative_path, void **buf, const char* optional_outfile)
|
||||||
{
|
{
|
||||||
CFileInStream archiveStream;
|
CFileInStream archiveStream;
|
||||||
CLookToRead lookStream;
|
CLookToRead lookStream;
|
||||||
@ -245,6 +250,9 @@ int read_7zip_file(const char * archive_path,
|
|||||||
|
|
||||||
if (strcmp(infile,relative_path) == 0)
|
if (strcmp(infile,relative_path) == 0)
|
||||||
{
|
{
|
||||||
|
/* C LZMA SDK does not support chunked extraction - see here:
|
||||||
|
* sourceforge.net/p/sevenzip/discussion/45798/thread/6fb59aaf/
|
||||||
|
* */
|
||||||
file_found = true;
|
file_found = true;
|
||||||
res = SzArEx_Extract(&db, &lookStream.s, i,&blockIndex,
|
res = SzArEx_Extract(&db, &lookStream.s, i,&blockIndex,
|
||||||
&outBuffer, &outBufferSize,&offset, &outSizeProcessed,
|
&outBuffer, &outBufferSize,&offset, &outSizeProcessed,
|
||||||
@ -254,17 +262,33 @@ int read_7zip_file(const char * archive_path,
|
|||||||
break; /* This goes to the error section. */
|
break; /* This goes to the error section. */
|
||||||
}
|
}
|
||||||
outsize = outSizeProcessed;
|
outsize = outSizeProcessed;
|
||||||
*buf = outBuffer+offset;
|
if (optional_outfile != NULL)
|
||||||
|
{
|
||||||
/*We could either use the 7Zip allocated buffer,
|
FILE* outsink = fopen(optional_outfile,"wb");
|
||||||
* or create our own and use it.
|
if (outsink == NULL)
|
||||||
* We would however need to realloc anyways, because RetroArch
|
{
|
||||||
* expects a \0 at the end, therefore we allocate new,
|
RARCH_ERR("Could not open outfilepath %s in 7zip_extract.\n",
|
||||||
* copy and free the old one. */
|
optional_outfile);
|
||||||
*buf = malloc(outsize + 1);
|
IAlloc_Free(&allocImp, outBuffer);
|
||||||
|
SzArEx_Free(&db, &allocImp);
|
||||||
((char*)(*buf))[outsize] = '\0';
|
SzFree(NULL, temp);
|
||||||
memcpy(*buf,outBuffer+offset,outsize);
|
File_Close(&archiveStream.file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fwrite(outBuffer+offset,1,outsize,outsink);
|
||||||
|
fclose(outsink);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*We could either use the 7Zip allocated buffer,
|
||||||
|
* or create our own and use it.
|
||||||
|
* We would however need to realloc anyways, because RetroArch
|
||||||
|
* expects a \0 at the end, therefore we allocate new,
|
||||||
|
* copy and free the old one. */
|
||||||
|
*buf = malloc(outsize + 1);
|
||||||
|
((char*)(*buf))[outsize] = '\0';
|
||||||
|
memcpy(*buf,outBuffer+offset,outsize);
|
||||||
|
}
|
||||||
IAlloc_Free(&allocImp, outBuffer);
|
IAlloc_Free(&allocImp, outBuffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -437,3 +461,5 @@ error:
|
|||||||
string_list_free(ext_list);
|
string_list_free(ext_list);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX
|
||||||
|
@ -21,7 +21,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int read_7zip_file(const char * archive_path,
|
int read_7zip_file(const char * archive_path,
|
||||||
const char *relative_path, void **buf);
|
const char *relative_path, void **buf, char const* optional_outfileq);
|
||||||
|
|
||||||
struct string_list *compressed_7zip_file_list_new(const char *path,
|
struct string_list *compressed_7zip_file_list_new(const char *path,
|
||||||
const char* ext);
|
const char* ext);
|
||||||
|
@ -26,15 +26,22 @@
|
|||||||
|
|
||||||
#include "../deps/rzlib/unzip.h"
|
#include "../deps/rzlib/unzip.h"
|
||||||
|
|
||||||
|
/* Undefined at the end of the file
|
||||||
|
* Don't use outside of this file
|
||||||
|
*/
|
||||||
|
#define RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX 16384
|
||||||
|
|
||||||
/* Extract the relative path relative_path from a
|
/* Extract the relative path relative_path from a
|
||||||
* zip archive archive_path and allocate a buf for it to write it in. */
|
* zip archive archive_path and allocate a buf for it to write it in. */
|
||||||
/* This code is inspired by:
|
/* This code is inspired by:
|
||||||
* stackoverflow.com/questions/10440113/simple-way-to-unzip-a-zip-file-using-zlib
|
* stackoverflow.com/questions/10440113/simple-way-to-unzip-a-zip-file-using-zlib
|
||||||
|
*
|
||||||
|
* optional_outfile if not NULL will be used to extract the file. buf will be 0
|
||||||
|
* then.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int read_zip_file(const char * archive_path,
|
int read_zip_file(const char * archive_path,
|
||||||
const char *relative_path, void **buf)
|
const char *relative_path, void **buf, const char* optional_outfile)
|
||||||
{
|
{
|
||||||
ssize_t bytes_read = -1;
|
ssize_t bytes_read = -1;
|
||||||
bool finished_reading = false;
|
bool finished_reading = false;
|
||||||
@ -94,22 +101,55 @@ int read_zip_file(const char * archive_path,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate outbuffer */
|
if (optional_outfile != 0)
|
||||||
*buf = malloc(file_info.uncompressed_size + 1 );
|
|
||||||
|
|
||||||
bytes_read = unzReadCurrentFile( zipfile, *buf, file_info.uncompressed_size );
|
|
||||||
if (bytes_read != file_info.uncompressed_size)
|
|
||||||
{
|
{
|
||||||
RARCH_ERR(
|
char read_buffer[RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX];
|
||||||
|
FILE* outsink = fopen(optional_outfile,"wb");
|
||||||
|
if (outsink == NULL)
|
||||||
|
{
|
||||||
|
RARCH_ERR("Could not open outfilepath %s in zip_extract.\n",
|
||||||
|
optional_outfile);
|
||||||
|
unzCloseCurrentFile( zipfile );
|
||||||
|
unzClose( zipfile );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bytes_read = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bytes_read = unzReadCurrentFile( zipfile, read_buffer,
|
||||||
|
RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX );
|
||||||
|
ssize_t fwrite_bytes = fwrite(read_buffer,1,bytes_read,outsink);
|
||||||
|
if (fwrite_bytes != bytes_read)
|
||||||
|
{
|
||||||
|
/* couldn't write all bytes */
|
||||||
|
RARCH_ERR("Error writing to %s.\n",optional_outfile);
|
||||||
|
fclose(outsink);
|
||||||
|
unzCloseCurrentFile( zipfile );
|
||||||
|
unzClose( zipfile );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while(bytes_read > 0) ;
|
||||||
|
fclose(outsink);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Allocate outbuffer */
|
||||||
|
*buf = malloc(file_info.uncompressed_size + 1 );
|
||||||
|
|
||||||
|
bytes_read = unzReadCurrentFile( zipfile, *buf, file_info.uncompressed_size );
|
||||||
|
if (bytes_read != file_info.uncompressed_size)
|
||||||
|
{
|
||||||
|
RARCH_ERR(
|
||||||
"We tried to read %d bytes, but only got %d of file %s in zip %s.\n",
|
"We tried to read %d bytes, but only got %d of file %s in zip %s.\n",
|
||||||
(unsigned int) file_info.uncompressed_size, (int)bytes_read,
|
(unsigned int) file_info.uncompressed_size, (int)bytes_read,
|
||||||
relative_path, archive_path);
|
relative_path, archive_path);
|
||||||
free(*buf);
|
free(*buf);
|
||||||
unzCloseCurrentFile( zipfile );
|
unzCloseCurrentFile( zipfile );
|
||||||
unzClose( zipfile );
|
unzClose( zipfile );
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
((char*)(*buf))[file_info.uncompressed_size] = '\0';
|
||||||
}
|
}
|
||||||
((char*)(*buf))[file_info.uncompressed_size] = '\0';
|
|
||||||
finished_reading = true;
|
finished_reading = true;
|
||||||
}
|
}
|
||||||
unzCloseCurrentFile( zipfile );
|
unzCloseCurrentFile( zipfile );
|
||||||
@ -238,3 +278,5 @@ struct string_list *compressed_zip_file_list_new(const char *path,
|
|||||||
unzClose( zipfile );
|
unzClose( zipfile );
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX
|
||||||
|
@ -21,7 +21,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int read_zip_file(const char * archive_path,
|
int read_zip_file(const char * archive_path,
|
||||||
const char *relative_path, void **buf);
|
const char *relative_path, void **buf, const char* optional_outfile);
|
||||||
|
|
||||||
struct string_list *compressed_zip_file_list_new(const char *path,
|
struct string_list *compressed_zip_file_list_new(const char *path,
|
||||||
const char* ext);
|
const char* ext);
|
||||||
|
15
file.c
15
file.c
@ -398,21 +398,12 @@ static bool load_content(const struct retro_subsystem_info *special,
|
|||||||
"extraction directory was not set or found. Exiting.\n");
|
"extraction directory was not set or found. Exiting.\n");
|
||||||
rarch_assert(false);
|
rarch_assert(false);
|
||||||
}
|
}
|
||||||
/* This is a test implementation, currently it needs as much
|
|
||||||
* RAM as the file is big.
|
|
||||||
*/
|
|
||||||
char new_path[PATH_MAX];
|
char new_path[PATH_MAX];
|
||||||
fill_pathname_join(new_path,g_settings.extraction_directory,
|
fill_pathname_join(new_path,g_settings.extraction_directory,
|
||||||
path_basename(path),sizeof(new_path));
|
path_basename(path),sizeof(new_path));
|
||||||
void *buf = NULL;
|
read_compressed_file(path,NULL,new_path);
|
||||||
ssize_t bytes_read = -1;
|
info[i].path = strdup(new_path);
|
||||||
bytes_read = read_file(path, &buf);
|
|
||||||
write_file(new_path,buf,bytes_read);
|
|
||||||
|
|
||||||
info[i].path =strdup(new_path);
|
|
||||||
if(buf)
|
|
||||||
free(buf);
|
|
||||||
buf = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
file_path.c
22
file_path.c
@ -92,10 +92,22 @@ bool write_empty_file(const char *path)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generic compressed file loader. */
|
/* Generic compressed file loader.
|
||||||
|
* Extracts to buf, unless optional_filename != 0
|
||||||
|
* Then extracts to optional_filename and leaves buf alone.
|
||||||
|
*/
|
||||||
#ifdef HAVE_COMPRESSION
|
#ifdef HAVE_COMPRESSION
|
||||||
long read_compressed_file(const char * path, void **buf)
|
long read_compressed_file(const char * path, void **buf,
|
||||||
|
const char* optional_filename)
|
||||||
{
|
{
|
||||||
|
/* Safety check.
|
||||||
|
* If optional_filename and optional_filename exists, we simply return 0,
|
||||||
|
* hoping that optional_filename is the same as requested.
|
||||||
|
*/
|
||||||
|
if (optional_filename)
|
||||||
|
if(path_file_exists(optional_filename))
|
||||||
|
return 0;
|
||||||
|
|
||||||
//We split carchive path and relative path:
|
//We split carchive path and relative path:
|
||||||
char archive_path[PATH_MAX];
|
char archive_path[PATH_MAX];
|
||||||
strlcpy(archive_path,path,sizeof(archive_path));
|
strlcpy(archive_path,path,sizeof(archive_path));
|
||||||
@ -123,11 +135,11 @@ long read_compressed_file(const char * path, void **buf)
|
|||||||
const char* file_ext = path_get_extension(archive_path);
|
const char* file_ext = path_get_extension(archive_path);
|
||||||
#ifdef HAVE_7ZIP
|
#ifdef HAVE_7ZIP
|
||||||
if (strcasecmp(file_ext,"7z") == 0)
|
if (strcasecmp(file_ext,"7z") == 0)
|
||||||
return read_7zip_file(archive_path,archive_found,buf);
|
return read_7zip_file(archive_path,archive_found,buf,optional_filename);
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_ZLIB
|
#ifdef HAVE_ZLIB
|
||||||
if (strcasecmp(file_ext,"zip") == 0)
|
if (strcasecmp(file_ext,"zip") == 0)
|
||||||
return read_zip_file(archive_path,archive_found,buf);
|
return read_zip_file(archive_path,archive_found,buf,optional_filename);
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -187,7 +199,7 @@ long read_file(const char *path, void **buf)
|
|||||||
* */
|
* */
|
||||||
#ifdef HAVE_COMPRESSION
|
#ifdef HAVE_COMPRESSION
|
||||||
if (path_contains_compressed_file(path))
|
if (path_contains_compressed_file(path))
|
||||||
return read_compressed_file(path,buf);
|
return read_compressed_file(path,buf,0);
|
||||||
#endif
|
#endif
|
||||||
return read_generic_file(path,buf);
|
return read_generic_file(path,buf);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,8 @@ enum
|
|||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_COMPRESSION
|
#ifdef HAVE_COMPRESSION
|
||||||
long read_compressed_file(const char * path, void **buf);
|
long read_compressed_file(const char * path, void **buf,
|
||||||
|
const char* optional_filename);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
long read_file(const char *path, void **buf);
|
long read_file(const char *path, void **buf);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user