diff --git a/libretro-common/file/archive_file.c b/libretro-common/file/archive_file.c index 0f19a40bc6..dda4281d3f 100644 --- a/libretro-common/file/archive_file.c +++ b/libretro-common/file/archive_file.c @@ -249,9 +249,22 @@ static int file_archive_extract_cb(const char *name, const char *valid_exts, path_basename(name), sizeof(new_path)); userdata->first_extracted_file_path = strdup(new_path); - userdata->found_file = file_archive_perform_mode(new_path, - valid_exts, cdata, cmode, csize, size, - 0, userdata); + + char wanted_file[PATH_MAX_LENGTH] = {0}; + const char *delim = path_get_archive_delim(userdata->archive_path); + + if (delim) + strlcpy(wanted_file, delim + 1, strlen(delim) + 1); + + if (!string_is_equal_noncase(userdata->extracted_file_path, + wanted_file)) + return 1; // keep searching for the right file + + if (file_archive_perform_mode(new_path, + valid_exts, cdata, cmode, csize, size, + 0, userdata)) + userdata->found_file = true; + return 0; } @@ -466,18 +479,19 @@ int file_archive_parse_file_progress(file_archive_transfer_t *state) } /** - * file_archive_extract_first_file: + * file_archive_extract_file: * @archive_path : filename path to archive. * @archive_path_size : size of archive. * @valid_exts : valid extensions for the file. * @extraction_directory : the directory to extract temporary * file to. * - * Extract first file from archive. + * Extract file from archive. If no file inside the archive is + * specified, the first file found will be used. * * Returns : true (1) on success, otherwise false (0). **/ -bool file_archive_extract_first_file( +bool file_archive_extract_file( char *archive_path, size_t archive_path_size, const char *valid_exts, @@ -506,6 +520,7 @@ bool file_archive_extract_first_file( userdata.ext = list; userdata.list = NULL; userdata.context = NULL; + userdata.list_only = false; if (!file_archive_parse_file(archive_path, valid_exts, file_archive_extract_cb, &userdata)) @@ -544,6 +559,7 @@ struct string_list *file_archive_get_file_list(const char *path, const char *valid_exts) { struct archive_extract_userdata userdata = {0}; + userdata.list_only = true; userdata.list = string_list_new(); diff --git a/libretro-common/file/archive_file_7z.c b/libretro-common/file/archive_file_7z.c index 3eacd25441..e35f7f146a 100644 --- a/libretro-common/file/archive_file_7z.c +++ b/libretro-common/file/archive_file_7z.c @@ -45,6 +45,8 @@ struct sevenzip_context_t { ISzAlloc allocImp; ISzAlloc allocTempImp; CSzArEx db; + size_t temp_size; + uint32_t block_index; uint32_t index; uint32_t packIndex; uint8_t *output; @@ -56,6 +58,8 @@ static void* sevenzip_stream_new(void) struct sevenzip_context_t *sevenzip_context = (struct sevenzip_context_t*)calloc(1, sizeof(struct sevenzip_context_t)); + fprintf(stderr, "7z: stream new\n"); + /* These are the allocation routines - currently using * the non-standard 7zip choices. */ sevenzip_context->allocImp.Alloc = SzAlloc; @@ -64,6 +68,8 @@ static void* sevenzip_stream_new(void) sevenzip_context->allocTempImp.Free = SzFreeTemp; sevenzip_context->index = 0; sevenzip_context->packIndex = 0; + sevenzip_context->temp_size = 0; + sevenzip_context->block_index = 0xFFFFFFFF; sevenzip_context->output = NULL; return sevenzip_context; @@ -73,6 +79,8 @@ static void sevenzip_stream_free(void *data) { struct sevenzip_context_t *sevenzip_context = (struct sevenzip_context_t*)data; + fprintf(stderr, "7z: stream free\n"); + if (!sevenzip_context) return; @@ -249,18 +257,6 @@ static int sevenzip_stream_decompress_data_to_file_iterate(void *data) struct sevenzip_context_t *sevenzip_context = (struct sevenzip_context_t*)data; - uint32_t block_index = 0xFFFFFFFF; - size_t offset = 0; - size_t outSizeProcessed = 0; - size_t output_size = 0; - - SRes res = SzArEx_Extract(&sevenzip_context->db, &sevenzip_context->lookStream.s, sevenzip_context->index, &block_index, - &sevenzip_context->output, &output_size, &offset, &outSizeProcessed, - &sevenzip_context->allocImp, &sevenzip_context->allocTempImp); - - if (res != SZ_OK) - return -1; - if (sevenzip_context->handle) sevenzip_context->handle->data = sevenzip_context->output; @@ -283,6 +279,8 @@ static int sevenzip_parse_file_init(file_archive_transfer_t *state, if (InFile_Open(&sevenzip_context->archiveStream.file, file)) return -1; + fprintf(stderr, "7z: open archive %s\n", file); + FileInStream_CreateVTable(&sevenzip_context->archiveStream); LookToRead_CreateVTable(&sevenzip_context->lookStream, False); sevenzip_context->lookStream.realStream = &sevenzip_context->archiveStream.s; @@ -300,9 +298,9 @@ static int sevenzip_parse_file_init(file_archive_transfer_t *state, static int sevenzip_parse_file_iterate_step_internal( file_archive_transfer_t *state, char *filename, - const uint8_t **cdata, - unsigned *cmode, uint32_t *size, uint32_t *csize, - uint32_t *checksum, unsigned *payback) + const uint8_t **cdata, unsigned *cmode, + uint32_t *size, uint32_t *csize, uint32_t *checksum, + unsigned *payback, struct archive_extract_userdata *userdata) { struct sevenzip_context_t *sevenzip_context = (struct sevenzip_context_t*)state->stream; const CSzFileItem *file = sevenzip_context->db.db.Files + sevenzip_context->index; @@ -341,6 +339,24 @@ static int sevenzip_parse_file_iterate_step_internal( strlcpy(filename, infile, PATH_MAX_LENGTH); + if (!userdata->list_only) + { + size_t output_size = 0; + size_t offset = 0; + size_t outSizeProcessed = 0; + + res = SzArEx_Extract(&sevenzip_context->db, + &sevenzip_context->lookStream.s, sevenzip_context->index, + &sevenzip_context->block_index, &sevenzip_context->output, + &output_size, &offset, &outSizeProcessed, + &sevenzip_context->allocImp, &sevenzip_context->allocTempImp); + + fprintf(stderr, "extract: %d\n", res == SZ_OK); + } + + if (res != SZ_OK) + return -1; + *cmode = ARCHIVE_MODE_COMPRESSED; *checksum = file->Crc; *size = file->Size; @@ -366,11 +382,15 @@ static int sevenzip_parse_file_iterate_step(file_archive_transfer_t *state, char filename[PATH_MAX_LENGTH] = {0}; int ret = sevenzip_parse_file_iterate_step_internal(state, filename, &cdata, &cmode, &size, &csize, - &checksum, &payload); + &checksum, &payload, userdata); if (ret != 1) return ret; + userdata->extracted_file_path = filename; + + fprintf(stderr, "set extracted path to %s\n", filename); + if (!file_cb(filename, valid_exts, cdata, cmode, csize, size, checksum, userdata)) return 0; diff --git a/libretro-common/file/archive_file_zlib.c b/libretro-common/file/archive_file_zlib.c index 462b682174..2aa998bd6e 100644 --- a/libretro-common/file/archive_file_zlib.c +++ b/libretro-common/file/archive_file_zlib.c @@ -447,6 +447,8 @@ static int zip_parse_file_iterate_step(file_archive_transfer_t *state, if (ret != 1) return ret; + userdata->extracted_file_path = filename; + if (!file_cb(filename, valid_exts, cdata, cmode, csize, size, checksum, userdata)) return 0; diff --git a/libretro-common/include/file/archive_file.h b/libretro-common/include/file/archive_file.h index 189360c1ec..cfc4f077b6 100644 --- a/libretro-common/include/file/archive_file.h +++ b/libretro-common/include/file/archive_file.h @@ -90,11 +90,13 @@ struct archive_extract_userdata { char *archive_path; char *first_extracted_file_path; + char *extracted_file_path; const char *extraction_directory; size_t archive_path_size; struct string_list *ext; struct string_list *list; bool found_file; + bool list_only; void *context; char archive_name[PATH_MAX_LENGTH]; uint32_t crc; @@ -151,18 +153,19 @@ void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state); int file_archive_parse_file_progress(file_archive_transfer_t *state); /** - * file_archive_extract_first_file: + * file_archive_extract_file: * @zip_path : filename path to ZIP archive. * @zip_path_size : size of ZIP archive. * @valid_exts : valid extensions for a file. * @extraction_directory : the directory to extract temporary * unzipped file to. * - * Extract first file from archive. + * Extract file from archive. If no file inside the archive is + * specified, the first file found will be used. * * Returns : true (1) on success, otherwise false (0). **/ -bool file_archive_extract_first_file(char *zip_path, size_t zip_path_size, +bool file_archive_extract_file(char *zip_path, size_t zip_path_size, const char *valid_exts, const char *extraction_dir, char *out_path, size_t len); diff --git a/tasks/task_content.c b/tasks/task_content.c index 738e6601af..d8e124e93f 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -525,7 +525,7 @@ static bool init_content_file_extract( strlcpy(temp_content, content->elems[i].data, sizeof(temp_content)); - if (!file_archive_extract_first_file(temp_content, + if (!file_archive_extract_file(temp_content, sizeof(temp_content), valid_ext, *settings->directory.cache ? settings->directory.cache : NULL,