diff --git a/configuration.c b/configuration.c index 59b4b0c720..d9b3ec572e 100644 --- a/configuration.c +++ b/configuration.c @@ -671,6 +671,7 @@ static void config_set_defaults(void) settings->bundle_assets_extract_last_version = 0; *settings->bundle_assets_src_path = '\0'; *settings->bundle_assets_dst_path = '\0'; + *settings->bundle_assets_dst_path_subdir = '\0'; *settings->playlist_names = '\0'; *settings->playlist_cores = '\0'; *settings->core_options_path = '\0'; @@ -1607,6 +1608,7 @@ static bool config_load_file(const char *path, bool set_defaults) CONFIG_GET_INT_BASE(conf, settings, bundle_assets_extract_last_version, "bundle_assets_extract_last_version"); config_get_array(conf, "bundle_assets_src_path", settings->bundle_assets_src_path, sizeof(settings->bundle_assets_src_path)); config_get_array(conf, "bundle_assets_dst_path", settings->bundle_assets_dst_path, sizeof(settings->bundle_assets_dst_path)); + config_get_array(conf, "bundle_assets_dst_path_subdir", settings->bundle_assets_dst_path_subdir, sizeof(settings->bundle_assets_dst_path_subdir)); CONFIG_GET_INT_BASE(conf, settings, rewind_granularity, "rewind_granularity"); CONFIG_GET_FLOAT_BASE(conf, settings, slowmotion_ratio, "slowmotion_ratio"); @@ -2541,6 +2543,7 @@ bool config_save_file(const char *path) config_set_int(conf, "bundle_assets_extract_last_version", settings->bundle_assets_extract_last_version); config_set_string(conf, "bundle_assets_src_path", settings->bundle_assets_src_path); config_set_string(conf, "bundle_assets_dst_path", settings->bundle_assets_dst_path); + config_set_string(conf, "bundle_assets_dst_path_subdir", settings->bundle_assets_dst_path_subdir); config_set_string(conf, "playlist_names", settings->playlist_names); config_set_string(conf, "playlist_cores", settings->playlist_cores); config_set_float(conf, "video_refresh_rate", settings->video.refresh_rate); diff --git a/configuration.h b/configuration.h index 1b7a630d74..6d9be0a267 100644 --- a/configuration.h +++ b/configuration.h @@ -307,6 +307,7 @@ typedef struct settings unsigned bundle_assets_extract_last_version; char bundle_assets_src_path[PATH_MAX_LENGTH]; char bundle_assets_dst_path[PATH_MAX_LENGTH]; + char bundle_assets_dst_path_subdir[PATH_MAX_LENGTH]; char core_options_path[PATH_MAX_LENGTH]; char content_history_path[PATH_MAX_LENGTH]; diff --git a/menu/cbs/menu_cbs_deferred_push.c b/menu/cbs/menu_cbs_deferred_push.c index 35094495d9..71ecdf1200 100644 --- a/menu/cbs/menu_cbs_deferred_push.c +++ b/menu/cbs/menu_cbs_deferred_push.c @@ -451,7 +451,7 @@ void cb_generic_download(void *task_data, void *user_data, const char *err) if (!strcasecmp(file_ext, "zip")) { - rarch_task_push_decompress(output_path, dir_path, NULL, + rarch_task_push_decompress(output_path, dir_path, NULL, NULL, cb_decompressed, (void*)(uintptr_t)transf->type_hash); } #else diff --git a/menu/menu.c b/menu/menu.c index 1b19fab7b7..aae1213168 100644 --- a/menu/menu.c +++ b/menu/menu.c @@ -281,8 +281,8 @@ void *menu_init(const void *data) settings->bundle_assets_extract_version_current != settings->bundle_assets_extract_last_version ) { - rarch_task_push_decompress(settings->bundle_assets_src_path, settings->bundle_assets_dst_path, NULL, - bundle_decompressed, NULL); + rarch_task_push_decompress(settings->bundle_assets_src_path, settings->bundle_assets_dst_path, + settings->bundle_assets_dst_path_subdir, NULL, bundle_decompressed, NULL); } #endif diff --git a/tasks/task_decompress.c b/tasks/task_decompress.c index 0ca0dda15b..d715c88803 100644 --- a/tasks/task_decompress.c +++ b/tasks/task_decompress.c @@ -25,8 +25,10 @@ #include "../verbosity.h" #include "../msg_hash.h" -typedef struct { +typedef struct +{ char *source_file; + char *subdir; char *target_dir; char *valid_ext; @@ -35,6 +37,46 @@ typedef struct { zlib_transfer_t zlib; } decompress_state_t; +static int file_decompressed_subdir(const char *name, const char *valid_exts, + const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, + uint32_t crc32, void *userdata) +{ + char path[PATH_MAX_LENGTH]; + char path_dir[PATH_MAX_LENGTH]; + decompress_state_t *dec = (decompress_state_t*)userdata; + + /* Ignore directories. */ + if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\') + goto next_file; + + if (strstr(name, dec->subdir) != name) + return 1; + + name += strlen(dec->subdir) + 1; + + fill_pathname_join(path, dec->target_dir, name, sizeof(path)); + fill_pathname_basedir(path_dir, path, sizeof(path_dir)); + + /* Make directory */ + if (!path_mkdir(path_dir)) + goto error; + + if (!zlib_perform_mode(path, valid_exts, + cdata, cmode, csize, size, crc32, userdata)) + goto error; + + RARCH_LOG("[deflate subdir] Path: %s, CRC32: 0x%x\n", name, crc32); + +next_file: + return 1; + +error: + dec->callback_error = (char*)malloc(PATH_MAX_LENGTH); + snprintf(dec->callback_error, PATH_MAX_LENGTH, "Failed to deflate %s.\n", path); + + return 0; +} + static int file_decompressed(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t crc32, void *userdata) @@ -71,14 +113,39 @@ error: return 0; } +static void rarch_task_decompress_handler_finished(rarch_task_t *task, + decompress_state_t *dec) +{ + + task->finished = true; + + if (!task->error && task->cancelled) + task->error = strdup("Task canceled"); + + if (!task->error) + { + decompress_task_data_t *data = + (decompress_task_data_t*)calloc(1, sizeof(*data)); + + data->source_file = dec->source_file; + task->task_data = data; + } + else + free(dec->source_file); + + if (dec->subdir) + free(dec->subdir); + if (dec->valid_ext) + free(dec->valid_ext); + free(dec->target_dir); + free(dec); +} + static void rarch_task_decompress_handler(rarch_task_t *task) { - decompress_state_t *dec = (decompress_state_t*)task->state; - decompress_task_data_t *data = NULL; bool returnerr; - int ret = 0; - - ret = zlib_parse_file_iterate(&dec->zlib, &returnerr, dec->source_file, + decompress_state_t *dec = (decompress_state_t*)task->state; + int ret = zlib_parse_file_iterate(&dec->zlib, &returnerr, dec->source_file, dec->valid_ext, file_decompressed, dec); task->progress = zlib_parse_file_progress(&dec->zlib); @@ -87,30 +154,27 @@ static void rarch_task_decompress_handler(rarch_task_t *task) { task->error = dec->callback_error; zlib_parse_file_iterate_stop(&dec->zlib); - goto task_finished; + + rarch_task_decompress_handler_finished(task, dec); } +} - return; +static void rarch_task_decompress_handler_subdir(rarch_task_t *task) +{ + bool returnerr; + decompress_state_t *dec = (decompress_state_t*)task->state; + int ret = zlib_parse_file_iterate(&dec->zlib, &returnerr, dec->source_file, + dec->valid_ext, file_decompressed_subdir, dec); -task_finished: - task->finished = true; + task->progress = zlib_parse_file_progress(&dec->zlib); - if (!task->error && task->cancelled) - task->error = strdup("Task canceled"); - - if (!task->error) + if (task->cancelled || ret != 0) { - data = (decompress_task_data_t*)calloc(1, sizeof(*data)); - data->source_file = dec->source_file; - task->task_data = data; - } - else - free(dec->source_file); + task->error = dec->callback_error; + zlib_parse_file_iterate_stop(&dec->zlib); - if (dec->valid_ext) - free(dec->valid_ext); - free(dec->target_dir); - free(dec); + rarch_task_decompress_handler_finished(task, dec); + } } static bool rarch_task_decompress_finder(rarch_task_t *task, void *user_data) @@ -124,7 +188,7 @@ static bool rarch_task_decompress_finder(rarch_task_t *task, void *user_data) } bool rarch_task_push_decompress(const char *source_file, const char *target_dir, - const char *valid_ext, rarch_task_callback_t cb, void *user_data) + const char *subdir, const char *valid_ext, rarch_task_callback_t cb, void *user_data) { decompress_state_t *s; rarch_task_t *t; @@ -166,8 +230,14 @@ bool rarch_task_push_decompress(const char *source_file, const char *target_dir, s->zlib.type = ZLIB_TRANSFER_INIT; t = (rarch_task_t*)calloc(1, sizeof(*t)); - t->handler = rarch_task_decompress_handler; t->state = s; + t->handler = rarch_task_decompress_handler; + + if (subdir && subdir[0] != '\0') + { + s->subdir = strdup(subdir); + t->handler = rarch_task_decompress_handler_subdir; + } t->callback = cb; t->user_data = user_data; diff --git a/tasks/tasks.h b/tasks/tasks.h index 9bdff08f25..b66086a7c2 100644 --- a/tasks/tasks.h +++ b/tasks/tasks.h @@ -163,7 +163,8 @@ typedef struct { } decompress_task_data_t; bool rarch_task_push_decompress(const char *source_file, const char *target_dir, - const char *valid_ext, rarch_task_callback_t cb, void *user_data); + const char *subdir, const char *valid_ext, + rarch_task_callback_t cb, void *user_data); #ifdef __cplusplus }