diff --git a/audio/audio_dsp_filter.c b/audio/audio_dsp_filter.c index 6f49734f2e..e837b39015 100644 --- a/audio/audio_dsp_filter.c +++ b/audio/audio_dsp_filter.c @@ -247,7 +247,7 @@ rarch_dsp_filter_t *rarch_dsp_filter_new( if (!frontend_driver_get_core_extension(ext_name, sizeof(ext_name))) goto error; - plugs = dir_list_new(basedir, ext_name, false, false); + plugs = dir_list_new(basedir, ext_name, false, false, false); if (!plugs) goto error; #endif diff --git a/cores/libretro-imageviewer/image_core.c b/cores/libretro-imageviewer/image_core.c index a5f5fb2eb9..7033e6abec 100644 --- a/cores/libretro-imageviewer/image_core.c +++ b/cores/libretro-imageviewer/image_core.c @@ -240,7 +240,7 @@ bool IMAGE_CORE_PREFIX(retro_load_game)(const struct retro_game_info *info) path_basedir(dir); file_list = dir_list_new(dir, IMAGE_CORE_PREFIX(valid_extensions), - false,false); + false,false,false); dir_list_sort(file_list, false); free(dir); diff --git a/database_info.c b/database_info.c index 7532dca02c..e426b14de2 100644 --- a/database_info.c +++ b/database_info.c @@ -404,7 +404,7 @@ database_info_handle_t *database_info_dir_init(const char *dir, if (!db) return NULL; - db->list = dir_list_new_special(dir, DIR_LIST_CORE_INFO, NULL); + db->list = dir_list_new_special(dir, DIR_LIST_RECURSIVE, NULL); if (!db->list) goto error; diff --git a/gfx/drivers_context/drm_ctx.c b/gfx/drivers_context/drm_ctx.c index 7690b613c2..3878dfc387 100644 --- a/gfx/drivers_context/drm_ctx.c +++ b/gfx/drivers_context/drm_ctx.c @@ -366,7 +366,7 @@ static void *gfx_ctx_drm_init(void *video_driver) return NULL; fd = -1; - gpu_descriptors = dir_list_new("/dev/dri", NULL, false, false); + gpu_descriptors = dir_list_new("/dev/dri", NULL, false, false, false); nextgpu: free_drm_resources(drm); diff --git a/gfx/video_filter.c b/gfx/video_filter.c index 90e78572ec..98d13d82f2 100644 --- a/gfx/video_filter.c +++ b/gfx/video_filter.c @@ -409,7 +409,7 @@ rarch_softfilter_t *rarch_softfilter_new(const char *filter_config, if (!frontend_driver_get_core_extension(ext_name, sizeof(ext_name))) goto error; - plugs = dir_list_new(basedir, ext_name, false, false); + plugs = dir_list_new(basedir, ext_name, false, false, false); if (!plugs) { diff --git a/libretro-common/include/lists/dir_list.h b/libretro-common/include/lists/dir_list.h index 2ef8f9ff81..771e0e2e1f 100644 --- a/libretro-common/include/lists/dir_list.h +++ b/libretro-common/include/lists/dir_list.h @@ -42,7 +42,7 @@ RETRO_BEGIN_DECLS * NULL in case of error. Has to be freed manually. **/ struct string_list *dir_list_new(const char *dir, const char *ext, - bool include_dirs, bool include_compressed); + bool include_dirs, bool include_compressed, bool recursive); /** * dir_list_sort: @@ -63,6 +63,17 @@ void dir_list_sort(struct string_list *list, bool dir_first); **/ void dir_list_free(struct string_list *list); +/** + * dir_list_read: + * @dir : directory path. + * @list : the string list to add files to + * + * Add files within a directory to an existing string list + * + * Returns: -1 on error, 0 on success. + **/ +int dir_list_read(const char *dir, struct string_list *list, struct string_list *ext_list, bool include_dirs, bool include_compressed, bool recursive); + RETRO_END_DECLS #endif diff --git a/libretro-common/lists/dir_list.c b/libretro-common/lists/dir_list.c index 80fa09b3cd..3a32be9bac 100644 --- a/libretro-common/lists/dir_list.c +++ b/libretro-common/lists/dir_list.c @@ -159,9 +159,8 @@ static int parse_dir_entry(const char *name, char *file_path, * NULL in case of error. Has to be freed manually. **/ struct string_list *dir_list_new(const char *dir, - const char *ext, bool include_dirs, bool include_compressed) + const char *ext, bool include_dirs, bool include_compressed, bool recursive) { - struct RDIR *entry = NULL; struct string_list *ext_list = NULL; struct string_list *list = NULL; @@ -171,13 +170,40 @@ struct string_list *dir_list_new(const char *dir, if (ext) ext_list = string_split(ext, "|"); - entry = retro_opendir(dir); + if(dir_list_read(dir, list, ext_list, include_dirs, include_compressed, recursive) == -1) { + string_list_free(list); + string_list_free(ext_list); + return NULL; + } + + string_list_free(ext_list); + return list; +} + +/** + * dir_list_read: + * @dir : directory path. + * @list : the string list to add files to + * @ext_list : the string list of extensions to include + * @include_dirs : include directories as part of the finished directory listing? + * @include_compressed : Only include files which match ext. Do not try to match compressed files, etc. + * + * Add files within a directory to an existing string list + * + * Returns: -1 on error, 0 on success. + **/ +int dir_list_read(const char *dir, struct string_list *list, struct string_list *ext_list, bool include_dirs, bool include_compressed, bool recursive) +{ + struct RDIR *entry = retro_opendir(dir); if (!entry) - goto error; + return -1; if (retro_dirent_error(entry)) - goto error; + { + retro_closedir(entry); + return -1; + } while (retro_readdir(entry)) { @@ -190,11 +216,21 @@ struct string_list *dir_list_new(const char *dir, fill_pathname_join(file_path, dir, name, sizeof(file_path)); is_dir = retro_dirent_is_dir(entry, file_path); + if(is_dir && recursive) { + if(strncmp(name, ".", 1) == 0 || strncmp(name, "..", 2) == 0) + continue; + + dir_list_read(file_path, list, ext_list, include_dirs, include_compressed, recursive); + } + ret = parse_dir_entry(name, file_path, is_dir, include_dirs, include_compressed, list, ext_list, file_ext); if (ret == -1) - goto error; + { + retro_closedir(entry); + return -1; + } if (ret == 1) continue; @@ -202,13 +238,5 @@ struct string_list *dir_list_new(const char *dir, retro_closedir(entry); - string_list_free(ext_list); - return list; - -error: - retro_closedir(entry); - - string_list_free(list); - string_list_free(ext_list); - return NULL; + return 0; } diff --git a/list_special.c b/list_special.c index 0f43dbe451..bfac49b46e 100644 --- a/list_special.c +++ b/list_special.c @@ -53,6 +53,7 @@ struct string_list *dir_list_new_special(const char *input_dir, const char *dir = NULL; const char *exts = NULL; bool include_dirs = false; + bool recursive = false; (void)input_dir; @@ -79,6 +80,16 @@ struct string_list *dir_list_new_special(const char *input_dir, exts = list->all_ext; } break; + case DIR_LIST_RECURSIVE: + { + core_info_list_t *list = NULL; + core_info_get_list(&list); + + dir = input_dir; + exts = list->all_ext; + recursive = true; + } + break; case DIR_LIST_SHADERS: { union string_list_elem_attr attr = {0}; @@ -124,7 +135,7 @@ struct string_list *dir_list_new_special(const char *input_dir, return NULL; } - return dir_list_new(dir, exts, include_dirs, type == DIR_LIST_CORE_INFO); + return dir_list_new(dir, exts, include_dirs, type == DIR_LIST_CORE_INFO, recursive); } struct string_list *string_list_new_special(enum string_list_type type, diff --git a/list_special.h b/list_special.h index d4e3c288f0..4af32c996d 100644 --- a/list_special.h +++ b/list_special.h @@ -31,7 +31,8 @@ enum dir_list_type DIR_LIST_COLLECTIONS, DIR_LIST_PLAIN, DIR_LIST_SHADERS, - DIR_LIST_AUTOCONFIG + DIR_LIST_AUTOCONFIG, + DIR_LIST_RECURSIVE }; enum string_list_type diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 889b0e2b80..44694a3f77 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -3172,7 +3172,7 @@ static int menu_displaylist_parse_playlists( return 0; } - str_list = dir_list_new(info->path, NULL, true, true); + str_list = dir_list_new(info->path, NULL, true, true, false); if (!str_list) { @@ -3281,7 +3281,7 @@ static int menu_displaylist_parse_cores( str_list = dir_list_new(info->path, filter_ext ? info->exts : NULL, - true, true); + true, true, false); { char out_dir[PATH_MAX_LENGTH] = {0}; @@ -3487,7 +3487,7 @@ static int menu_displaylist_parse_generic( else str_list = dir_list_new(info->path, filter_ext ? info->exts : NULL, - true, true); + true, true, false); #ifdef HAVE_LIBRETRODB if (BIT32_GET(filebrowser_types, FILEBROWSER_SCAN_DIR))