From e6fc4220fa03e8df6ae1331e16b5b63fb394b482 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Wed, 16 Jan 2019 21:01:29 +0100 Subject: [PATCH 1/4] Revert "Revert "VFS v3: stat, mkdir, directory listings"" This reverts commit a549e28f0101cf42b6ee6ef4834ddcf983f0b448. --- dynamic.c | 24 +- libretro-common/file/file_path.c | 191 ++----- libretro-common/file/retro_dirent.c | 330 ++---------- libretro-common/include/file/file_path.h | 7 +- libretro-common/include/libretro.h | 55 +- libretro-common/include/retro_dirent.h | 15 +- .../include/vfs/vfs_implementation.h | 22 +- libretro-common/lists/dir_list.c | 6 +- libretro-common/vfs/vfs_implementation.c | 493 +++++++++++++++++- 9 files changed, 702 insertions(+), 441 deletions(-) diff --git a/dynamic.c b/dynamic.c index d00ea50160..a6d3074013 100644 --- a/dynamic.c +++ b/dynamic.c @@ -1927,9 +1927,10 @@ bool rarch_environment_cb(unsigned cmd, void *data) case RETRO_ENVIRONMENT_GET_VFS_INTERFACE: { - const uint32_t supported_vfs_version = 1; + const uint32_t supported_vfs_version = 3; static struct retro_vfs_interface vfs_iface = - { + { + /* VFS API v1 */ retro_vfs_file_get_path_impl, retro_vfs_file_open_impl, retro_vfs_file_close_impl, @@ -1939,15 +1940,32 @@ bool rarch_environment_cb(unsigned cmd, void *data) retro_vfs_file_read_impl, retro_vfs_file_write_impl, retro_vfs_file_flush_impl, - retro_vfs_file_remove_impl + retro_vfs_file_remove_impl, + retro_vfs_file_rename_impl, + /* VFS API v2 */ + retro_vfs_file_truncate_impl, + /* VFS API v3 */ + retro_vfs_stat_impl, + retro_vfs_mkdir_impl, + retro_vfs_opendir_impl, + retro_vfs_readdir_impl, + retro_vfs_dirent_get_name_impl, + retro_vfs_dirent_is_dir_impl, + retro_vfs_closedir_impl }; struct retro_vfs_interface_info *vfs_iface_info = (struct retro_vfs_interface_info *) data; if (vfs_iface_info->required_interface_version <= supported_vfs_version) { + RARCH_LOG("Core requested VFS version >= v%d, providing v%d\n", vfs_iface_info->required_interface_version, supported_vfs_version); vfs_iface_info->required_interface_version = supported_vfs_version; vfs_iface_info->iface = &vfs_iface; } + else + { + RARCH_WARN("Core requested VFS version v%d which is higher than what we support (v%d)\n", vfs_iface_info->required_interface_version, supported_vfs_version); + return false; + } break; } diff --git a/libretro-common/file/file_path.c b/libretro-common/file/file_path.c index c2d9459908..07b19e67fe 100644 --- a/libretro-common/file/file_path.c +++ b/libretro-common/file/file_path.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2018 The RetroArch team +/* Copyright (C) 2010-2019 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_path.c). @@ -32,7 +32,10 @@ #include #include #include +#define VFS_FRONTEND +#include +/* TODO: There are probably some unnecessary things on this huge include list now but I'm too afraid to touch it */ #ifdef __APPLE__ #include #endif @@ -116,118 +119,39 @@ #endif -enum stat_mode +static retro_vfs_stat_t path_stat_cb = NULL; +static retro_vfs_mkdir_t path_mkdir_cb = NULL; + +void path_vfs_init(const struct retro_vfs_interface_info* vfs_info) { - IS_DIRECTORY = 0, - IS_CHARACTER_SPECIAL, - IS_VALID -}; + const struct retro_vfs_interface* vfs_iface; -static bool path_stat(const char *path, enum stat_mode mode, int32_t *size) + path_stat_cb = NULL; + path_mkdir_cb = NULL; + + vfs_iface = vfs_info->iface; + + if (vfs_info->required_interface_version < PATH_REQUIRED_VFS_VERSION || !vfs_iface) + return; + + path_stat_cb = vfs_iface->stat; + path_mkdir_cb = vfs_iface->mkdir; +} + +static int path_stat(const char *path, int32_t *size) { -#if defined(ORBIS) - return false; /* for now */ -#endif -#if defined(VITA) || defined(PSP) - SceIoStat buf; - char *tmp = strdup(path); - size_t len = strlen(tmp); - if (tmp[len-1] == '/') - tmp[len-1] = '\0'; + if (path_stat_cb != NULL) + return path_stat_cb(path, NULL); + else + return retro_vfs_stat_impl(path, NULL); +} - if (sceIoGetstat(tmp, &buf) < 0) - { - free(tmp); - return false; - } - free(tmp); -#elif defined(PS2) - iox_stat_t buf; - char *tmp = strdup(path); - size_t len = strlen(tmp); - if (tmp[len-1] == '/') - tmp[len-1] = '\0'; - - if (fileXioGetStat(tmp, &buf) < 0) - { - free(tmp); - return false; - } - free(tmp); -#elif defined(__CELLOS_LV2__) - CellFsStat buf; - if (cellFsStat(path, &buf) < 0) - return false; -#elif defined(_WIN32) - DWORD file_info; - struct _stat buf; - char *path_local = NULL; - wchar_t *path_wide = NULL; - - if (!path || !*path) - return false; - - (void)path_wide; - (void)path_local; - (void)file_info; - -#if defined(LEGACY_WIN32) - path_local = utf8_to_local_string_alloc(path); - file_info = GetFileAttributes(path_local); - - _stat(path_local, &buf); - - if (path_local) - free(path_local); -#else - path_wide = utf8_to_utf16_string_alloc(path); - file_info = GetFileAttributesW(path_wide); - - _wstat(path_wide, &buf); - - if (path_wide) - free(path_wide); -#endif - - if (file_info == INVALID_FILE_ATTRIBUTES) - return false; -#else - struct stat buf; - if (stat(path, &buf) < 0) - return false; -#endif - - if (size) -#if defined(PS2) - *size = (int32_t)buf.size; -#else - *size = (int32_t)buf.st_size; -#endif - switch (mode) - { - case IS_DIRECTORY: -#if defined(VITA) || defined(PSP) - return FIO_S_ISDIR(buf.st_mode); -#elif defined(PS2) - return FIO_S_ISDIR(buf.mode); -#elif defined(__CELLOS_LV2__) - return ((buf.st_mode & S_IFMT) == S_IFDIR); -#elif defined(_WIN32) - return (file_info & FILE_ATTRIBUTE_DIRECTORY); -#else - return S_ISDIR(buf.st_mode); -#endif - case IS_CHARACTER_SPECIAL: -#if defined(VITA) || defined(PSP) || defined(PS2) || defined(__CELLOS_LV2__) || defined(_WIN32) - return false; -#else - return S_ISCHR(buf.st_mode); -#endif - case IS_VALID: - return true; - } - - return false; +static int path_mkdir_norecurse(const char *dir) +{ + if (path_mkdir_cb != NULL) + return path_mkdir_cb(dir); + else + return retro_vfs_mkdir_impl(dir); } /** @@ -241,6 +165,7 @@ static bool path_stat(const char *path, enum stat_mode mode, int32_t *size) bool path_is_directory(const char *path) { #ifdef ORBIS + /* TODO: This should be moved to the VFS module */ int dfd; if (!path) return false; @@ -250,40 +175,29 @@ bool path_is_directory(const char *path) orbisDclose(dfd); return true; #else - return path_stat(path, IS_DIRECTORY, NULL); + return (path_stat(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0; #endif } bool path_is_character_special(const char *path) { - return path_stat(path, IS_CHARACTER_SPECIAL, NULL); + return (path_stat(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0; } bool path_is_valid(const char *path) { - return path_stat(path, IS_VALID, NULL); + return (path_stat(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0; } int32_t path_get_size(const char *path) { int32_t filesize = 0; - if (path_stat(path, IS_VALID, &filesize)) + if (path_stat(path, &filesize) != 0) return filesize; return -1; } -static bool path_mkdir_error(int ret) -{ -#if defined(VITA) - return (ret == SCE_ERROR_ERRNO_EEXIST); -#elif defined(PSP) || defined(PS2) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(ORBIS) - return (ret == -1); -#else - return (ret < 0 && errno == EEXIST); -#endif -} - /** * path_mkdir: * @dir : directory @@ -329,35 +243,10 @@ bool path_mkdir(const char *dir) if (norecurse) { -#if defined(_WIN32) -#ifdef LEGACY_WIN32 - int ret = _mkdir(dir); -#else - wchar_t *dirW = utf8_to_utf16_string_alloc(dir); - int ret = -1; - - if (dirW) - { - ret = _wmkdir(dirW); - free(dirW); - } -#endif -#elif defined(IOS) - int ret = mkdir(dir, 0755); -#elif defined(VITA) || defined(PSP) - int ret = sceIoMkdir(dir, 0777); -#elif defined(PS2) - int ret =fileXioMkdir(dir, 0777); -#elif defined(ORBIS) - int ret =orbisMkdir(dir, 0755); -#elif defined(__QNX__) - int ret = mkdir(dir, 0777); -#else - int ret = mkdir(dir, 0750); -#endif + int ret = path_mkdir_norecurse(dir); /* Don't treat this as an error. */ - if (path_mkdir_error(ret) && path_is_directory(dir)) + if (ret == -2 && path_is_directory(dir)) ret = 0; if (ret < 0) diff --git a/libretro-common/file/retro_dirent.c b/libretro-common/file/retro_dirent.c index bf11e06654..353a12e81b 100644 --- a/libretro-common/file/retro_dirent.c +++ b/libretro-common/file/retro_dirent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2018 The RetroArch team +/* Copyright (C) 2010-2019 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_dirent.c). @@ -28,313 +28,95 @@ #include #include -#include -#include -#include +#define VFS_FRONTEND +#include -#if defined(_WIN32) -# ifdef _MSC_VER -# define setmode _setmode -# endif -#include -# ifdef _XBOX -# include -# define INVALID_FILE_ATTRIBUTES -1 -# else -# include -# include -# include -# include -# endif -#elif defined(VITA) -# include -# include -# include -#elif defined(ORBIS) -# include -# include -# include -# include -#else -# if defined(PSP) -# include -# endif -# if defined(PS2) -# include -# endif -# include -# include -# include -# include -#endif +static retro_vfs_opendir_t dirent_opendir_cb = NULL; +static retro_vfs_readdir_t dirent_readdir_cb = NULL; +static retro_vfs_dirent_get_name_t dirent_dirent_get_name_cb = NULL; +static retro_vfs_dirent_is_dir_t dirent_dirent_is_dir_cb = NULL; +static retro_vfs_closedir_t dirent_closedir_cb = NULL; -#ifdef __CELLOS_LV2__ -#include -#endif - -#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) || defined(PS2) -#include /* stat() is defined here */ -#endif - -#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX) -#ifndef LEGACY_WIN32 -#define LEGACY_WIN32 -#endif -#endif - -struct RDIR +void dirent_vfs_init(const struct retro_vfs_interface_info* vfs_info) { -#if defined(_WIN32) -#if defined(LEGACY_WIN32) - WIN32_FIND_DATA entry; -#else - WIN32_FIND_DATAW entry; -#endif - HANDLE directory; - bool next; - char path[PATH_MAX_LENGTH]; -#elif defined(VITA) || defined(PSP) - SceUID directory; - SceIoDirent entry; -#elif defined(PS2) - int directory; - iox_dirent_t entry; -#elif defined(__CELLOS_LV2__) - CellFsErrno error; - int directory; - CellFsDirent entry; -#elif defined(ORBIS) - int directory; - struct dirent entry; -#else - DIR *directory; - const struct dirent *entry; -#endif -}; + const struct retro_vfs_interface* vfs_iface; + + dirent_opendir_cb = NULL; + dirent_readdir_cb = NULL; + dirent_dirent_get_name_cb = NULL; + dirent_dirent_is_dir_cb = NULL; + dirent_closedir_cb = NULL; + + vfs_iface = vfs_info->iface; + + if (vfs_info->required_interface_version < DIRENT_REQUIRED_VFS_VERSION || !vfs_iface) + return; + + dirent_opendir_cb = vfs_iface->opendir; + dirent_readdir_cb = vfs_iface->readdir; + dirent_dirent_get_name_cb = vfs_iface->dirent_get_name; + dirent_dirent_is_dir_cb = vfs_iface->dirent_is_dir; + dirent_closedir_cb = vfs_iface->closedir; +} + +struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden) +{ + if (dirent_opendir_cb != NULL) + return (struct RDIR *)dirent_opendir_cb(name, include_hidden); + else + return (struct RDIR *)retro_vfs_opendir_impl(name, include_hidden); +} struct RDIR *retro_opendir(const char *name) { -#if defined(_WIN32) - char path_buf[1024]; - char *path_local = NULL; - wchar_t *path_wide = NULL; - unsigned path_len; -#endif - struct RDIR *rdir; - - /*Reject null or empty string paths*/ - if (!name||(*name==0)) - return NULL; - - /*Allocate RDIR struct. Tidied later with retro_closedir*/ - rdir = (struct RDIR*)calloc(1, sizeof(*rdir)); - if (!rdir) - return NULL; - -#if defined(_WIN32) - (void)path_wide; - (void)path_local; - - path_buf[0] = '\0'; - path_len = strlen(name); - - /* Non-NT platforms don't like extra slashes in the path */ - if (name[path_len - 1] == '\\') - snprintf(path_buf, sizeof(path_buf), "%s*", name); - else - snprintf(path_buf, sizeof(path_buf), "%s\\*", name); - -#if defined(LEGACY_WIN32) - path_local = utf8_to_local_string_alloc(path_buf); - rdir->directory = FindFirstFile(path_local, &rdir->entry); - - if (path_local) - free(path_local); -#else - path_wide = utf8_to_utf16_string_alloc(path_buf); - rdir->directory = FindFirstFileW(path_wide, &rdir->entry); - - if (path_wide) - free(path_wide); -#endif - -#elif defined(VITA) || defined(PSP) - rdir->directory = sceIoDopen(name); -#elif defined(PS2) - rdir->directory = fileXioDopen(name); -#elif defined(_3DS) - rdir->directory = !string_is_empty(name) ? opendir(name) : NULL; - rdir->entry = NULL; -#elif defined(__CELLOS_LV2__) - rdir->error = cellFsOpendir(name, &rdir->directory); -#elif defined(ORBIS) - rdir->directory = orbisDopen(name); -#else - rdir->directory = opendir(name); - rdir->entry = NULL; -#endif - - if (rdir->directory) - return rdir; - - free(rdir); - return NULL; + return retro_opendir_include_hidden(name, false); } bool retro_dirent_error(struct RDIR *rdir) { -#if defined(_WIN32) - return (rdir->directory == INVALID_HANDLE_VALUE); -#elif defined(VITA) || defined(PSP) || defined(PS2) || defined(ORBIS) - return (rdir->directory < 0); -#elif defined(__CELLOS_LV2__) - return (rdir->error != CELL_FS_SUCCEEDED); -#else - return !(rdir->directory); -#endif + /* Left for compatibility */ + return false; } int retro_readdir(struct RDIR *rdir) { -#if defined(_WIN32) - if(rdir->next) -#if defined(LEGACY_WIN32) - return (FindNextFile(rdir->directory, &rdir->entry) != 0); -#else - return (FindNextFileW(rdir->directory, &rdir->entry) != 0); -#endif - - rdir->next = true; - return (rdir->directory != INVALID_HANDLE_VALUE); -#elif defined(VITA) || defined(PSP) - return (sceIoDread(rdir->directory, &rdir->entry) > 0); -#elif defined(PS2) - iox_dirent_t record; - int ret = fileXioDread(rdir->directory, &record); - rdir->entry = record; - return ( ret > 0); -#elif defined(__CELLOS_LV2__) - uint64_t nread; - rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread); - return (nread != 0); -#elif defined(ORBIS) - return (orbisDread(rdir->directory, &rdir->entry) > 0); -#else - return ((rdir->entry = readdir(rdir->directory)) != NULL); -#endif + if (dirent_readdir_cb != NULL) + return dirent_readdir_cb((struct retro_vfs_dir_handle *)rdir); + else + return retro_vfs_readdir_impl((struct retro_vfs_dir_handle *)rdir); } const char *retro_dirent_get_name(struct RDIR *rdir) { -#if defined(_WIN32) -#if defined(LEGACY_WIN32) - char *name_local = local_to_utf8_string_alloc(rdir->entry.cFileName); - memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName)); - strlcpy(rdir->entry.cFileName, name_local, sizeof(rdir->entry.cFileName)); - - if (name_local) - free(name_local); -#else - char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName); - memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName)); - strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName)); - - if (name) - free(name); -#endif - return (char*)rdir->entry.cFileName; -#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(ORBIS) - return rdir->entry.d_name; -#elif defined(PS2) - return rdir->entry.name; -#else - - return rdir->entry->d_name; -#endif + if (dirent_dirent_get_name_cb != NULL) + return dirent_dirent_get_name_cb((struct retro_vfs_dir_handle *)rdir); + else + return retro_vfs_dirent_get_name_impl((struct retro_vfs_dir_handle *)rdir); } /** * * retro_dirent_is_dir: * @rdir : pointer to the directory entry. - * @path : path to the directory entry. + * @unused : deprecated, included for compatibility reasons, pass NULL * * Is the directory listing entry a directory? * * Returns: true if directory listing entry is * a directory, false if not. */ -bool retro_dirent_is_dir(struct RDIR *rdir, const char *path) +bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused) { -#if defined(_WIN32) - const WIN32_FIND_DATA *entry = (const WIN32_FIND_DATA*)&rdir->entry; - return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; -#elif defined(PSP) || defined(VITA) - const SceIoDirent *entry = (const SceIoDirent*)&rdir->entry; -#if defined(PSP) - return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR; -#elif defined(VITA) - return SCE_S_ISDIR(entry->d_stat.st_mode); -#endif -#elif defined(PS2) - const iox_dirent_t *entry = (const iox_dirent_t*)&rdir->entry; - return FIO_S_ISDIR(entry->stat.mode); -#elif defined(__CELLOS_LV2__) - CellFsDirent *entry = (CellFsDirent*)&rdir->entry; - return (entry->d_type == CELL_FS_TYPE_DIRECTORY); -#elif defined(ORBIS) - const struct dirent *entry = &rdir->entry; - if (entry->d_type==DT_DIR) - return true; - if (!(entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK)) - return false; -#else - struct stat buf; -#if defined(DT_DIR) - const struct dirent *entry = (const struct dirent*)rdir->entry; - if (entry->d_type == DT_DIR) - return true; - /* This can happen on certain file systems. */ - if (!(entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK)) - return false; -#endif - /* dirent struct doesn't have d_type, do it the slow way ... */ - if (stat(path, &buf) < 0) - return false; - return S_ISDIR(buf.st_mode); -#endif -} - -void retro_dirent_include_hidden(struct RDIR *rdir, bool include_hidden) -{ -#ifdef _WIN32 - if (include_hidden) - rdir->entry.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN; + if (dirent_dirent_is_dir_cb != NULL) + return dirent_dirent_is_dir_cb((struct retro_vfs_dir_handle *)rdir); else - rdir->entry.dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN; -#endif + return retro_vfs_dirent_is_dir_impl((struct retro_vfs_dir_handle *)rdir); } void retro_closedir(struct RDIR *rdir) { - if (!rdir) - return; - -#if defined(_WIN32) - if (rdir->directory != INVALID_HANDLE_VALUE) - FindClose(rdir->directory); -#elif defined(VITA) || defined(PSP) - sceIoDclose(rdir->directory); -#elif defined(PS2) - fileXioDclose(rdir->directory); -#elif defined(__CELLOS_LV2__) - rdir->error = cellFsClosedir(rdir->directory); -#elif defined(ORBIS) - orbisDclose(rdir->directory); -#else - if (rdir->directory) - closedir(rdir->directory); -#endif - - free(rdir); + if (dirent_closedir_cb != NULL) + dirent_closedir_cb((struct retro_vfs_dir_handle *)rdir); + else + retro_vfs_closedir_impl((struct retro_vfs_dir_handle *)rdir); } diff --git a/libretro-common/include/file/file_path.h b/libretro-common/include/file/file_path.h index c6896e05ab..e894bebdc3 100644 --- a/libretro-common/include/file/file_path.h +++ b/libretro-common/include/file/file_path.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2018 The RetroArch team +/* Copyright (C) 2010-2019 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_path.h). @@ -28,12 +28,17 @@ #include #include +#include #include #include RETRO_BEGIN_DECLS +#define PATH_REQUIRED_VFS_VERSION 3 + +void path_vfs_init(const struct retro_vfs_interface_info* vfs_info); + /* Order in this enum is equivalent to negative sort order in filelist * (i.e. DIRECTORY is on top of PLAIN_FILE) */ enum diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index 4e1a9785ba..2f077c5522 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -1100,6 +1100,10 @@ enum retro_mod * Introduced in VFS API v1 */ struct retro_vfs_file_handle; +/* Opaque directory handle + * Introduced in VFS API v3 */ +struct retro_vfs_dir_handle; + /* File open flags * Introduced in VFS API v1 */ #define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */ @@ -1119,6 +1123,12 @@ struct retro_vfs_file_handle; #define RETRO_VFS_SEEK_POSITION_CURRENT 1 #define RETRO_VFS_SEEK_POSITION_END 2 +/* stat() result flags + * Introduced in VFS API v3 */ +#define RETRO_VFS_STAT_IS_VALID (1 << 0) +#define RETRO_VFS_STAT_IS_DIRECTORY (1 << 1) +#define RETRO_VFS_STAT_IS_CHARACTER_SPECIAL (1 << 2) + /* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle * Introduced in VFS API v1 */ typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream); @@ -1128,7 +1138,7 @@ typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file * Introduced in VFS API v1 */ typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints); -/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on succes, -1 on failure. +/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on success, -1 on failure. * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. * Introduced in VFS API v1 */ typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream); @@ -1141,7 +1151,7 @@ typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle * Introduced in VFS API v2 */ typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length); -/* Get the current read / write position for the file. Returns - 1 for error. +/* Get the current read / write position for the file. Returns -1 for error. * Introduced in VFS API v1 */ typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream); @@ -1169,6 +1179,39 @@ typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path); * Introduced in VFS API v1 */ typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path); +/* Stat the specified file. Retruns a bitmask of RETRO_VFS_STAT_* flags, none are set if path was not valid. + * Additionally stores file size in given variable, unless NULL is given. + * Introduced in VFS API v3 */ +typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size); + +/* Create the specified directory. Returns 0 on success, -1 on unknown failure, -2 if already exists. + * Introduced in VFS API v3 */ +typedef int (RETRO_CALLCONV *retro_vfs_mkdir_t)(const char *dir); + +/* Open the specified directory for listing. Returns the opaque dir handle, or NULL for error. + * Support for the include_hidden argument may vary depending on the platform. + * Introduced in VFS API v3 */ +typedef struct retro_vfs_dir_handle *(RETRO_CALLCONV *retro_vfs_opendir_t)(const char *dir, bool include_hidden); + +/* Read the directory entry at the current position, and move the read pointer to the next position. + * Returns true on success, false if already on the last entry. + * Introduced in VFS API v3 */ +typedef bool (RETRO_CALLCONV *retro_vfs_readdir_t)(struct retro_vfs_dir_handle *dirstream); + +/* Get the name of the last entry read. Returns a string on success, or NULL for error. + * The returned string pointer is valid until the next call to readdir or closedir. + * Introduced in VFS API v3 */ +typedef const char *(RETRO_CALLCONV *retro_vfs_dirent_get_name_t)(struct retro_vfs_dir_handle *dirstream); + +/* Check if the last entry read was a directory. Returns true if it was, false otherwise (or on error). + * Introduced in VFS API v3 */ +typedef bool (RETRO_CALLCONV *retro_vfs_dirent_is_dir_t)(struct retro_vfs_dir_handle *dirstream); + +/* Close the directory and release its resources. Must be called if opendir returns non-NULL. Returns 0 on success, -1 on failure. + * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. + * Introduced in VFS API v3 */ +typedef int (RETRO_CALLCONV *retro_vfs_closedir_t)(struct retro_vfs_dir_handle *dirstream); + struct retro_vfs_interface { /* VFS API v1 */ @@ -1185,6 +1228,14 @@ struct retro_vfs_interface retro_vfs_rename_t rename; /* VFS API v2 */ retro_vfs_truncate_t truncate; + /* VFS API v3 */ + retro_vfs_stat_t stat; + retro_vfs_mkdir_t mkdir; + retro_vfs_opendir_t opendir; + retro_vfs_readdir_t readdir; + retro_vfs_dirent_get_name_t dirent_get_name; + retro_vfs_dirent_is_dir_t dirent_is_dir; + retro_vfs_closedir_t closedir; }; struct retro_vfs_interface_info diff --git a/libretro-common/include/retro_dirent.h b/libretro-common/include/retro_dirent.h index c3450732c5..8a2591bd3a 100644 --- a/libretro-common/include/retro_dirent.h +++ b/libretro-common/include/retro_dirent.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2018 The RetroArch team +/* Copyright (C) 2010-2019 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_dirent.h). @@ -23,6 +23,7 @@ #ifndef __RETRO_DIRENT_H #define __RETRO_DIRENT_H +#include #include #include @@ -30,6 +31,10 @@ RETRO_BEGIN_DECLS +#define DIRENT_REQUIRED_VFS_VERSION 3 + +void dirent_vfs_init(const struct retro_vfs_interface_info* vfs_info); + typedef struct RDIR RDIR; /** @@ -44,25 +49,27 @@ typedef struct RDIR RDIR; */ struct RDIR *retro_opendir(const char *name); +struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden); + int retro_readdir(struct RDIR *rdir); +/* Deprecated, returns false, left for compatibility */ bool retro_dirent_error(struct RDIR *rdir); -void retro_dirent_include_hidden(struct RDIR *rdir, bool include_hidden); - const char *retro_dirent_get_name(struct RDIR *rdir); /** * * retro_dirent_is_dir: * @rdir : pointer to the directory entry. + * @unused : deprecated, included for compatibility reasons, pass NULL * * Is the directory listing entry a directory? * * Returns: true if directory listing entry is * a directory, false if not. */ -bool retro_dirent_is_dir(struct RDIR *rdir, const char *path); +bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused); void retro_closedir(struct RDIR *rdir); diff --git a/libretro-common/include/vfs/vfs_implementation.h b/libretro-common/include/vfs/vfs_implementation.h index 5a1e5c3a9c..afc2e22213 100644 --- a/libretro-common/include/vfs/vfs_implementation.h +++ b/libretro-common/include/vfs/vfs_implementation.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2018 The RetroArch team +/* Copyright (C) 2010-2019 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vfs_implementation.h). @@ -38,6 +38,12 @@ typedef struct retro_vfs_file_handle libretro_vfs_implementation_file; typedef struct libretro_vfs_implementation_file libretro_vfs_implementation_file; #endif +#ifdef VFS_FRONTEND +typedef struct retro_vfs_dir_handle libretro_vfs_implementation_dir; +#else +typedef struct libretro_vfs_implementation_dir libretro_vfs_implementation_dir; +#endif + libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints); int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream); @@ -64,4 +70,18 @@ int retro_vfs_file_rename_impl(const char *old_path, const char *new_path); const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *stream); +int retro_vfs_stat_impl(const char *path, int32_t *size); + +int retro_vfs_mkdir_impl(const char *dir); + +libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *dir, bool include_hidden); + +bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *dirstream); + +const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *dirstream); + +bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *dirstream); + +int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *dirstream); + #endif diff --git a/libretro-common/lists/dir_list.c b/libretro-common/lists/dir_list.c index 0972ec84f0..6afc3fab30 100644 --- a/libretro-common/lists/dir_list.c +++ b/libretro-common/lists/dir_list.c @@ -171,13 +171,11 @@ static int dir_list_read(const char *dir, bool include_dirs, bool include_hidden, bool include_compressed, bool recursive) { - struct RDIR *entry = retro_opendir(dir); + struct RDIR *entry = retro_opendir_include_hidden(dir, include_hidden); if (!entry || retro_dirent_error(entry)) goto error; - retro_dirent_include_hidden(entry, include_hidden); - while (retro_readdir(entry)) { char file_path[PATH_MAX_LENGTH]; @@ -189,7 +187,7 @@ static int dir_list_read(const char *dir, file_path[0] = '\0'; fill_pathname_join(file_path, dir, name, sizeof(file_path)); - is_dir = retro_dirent_is_dir(entry, file_path); + is_dir = retro_dirent_is_dir(entry, NULL); if(!is_dir) file_ext = path_get_extension(name); diff --git a/libretro-common/vfs/vfs_implementation.c b/libretro-common/vfs/vfs_implementation.c index c2232fd6c5..693ecfd748 100644 --- a/libretro-common/vfs/vfs_implementation.c +++ b/libretro-common/vfs/vfs_implementation.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2018 The RetroArch team +/* Copyright (C) 2010-2019 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vfs_implementation.c). @@ -34,6 +34,7 @@ # ifdef _MSC_VER # define setmode _setmode # endif +#include # ifdef _XBOX # include # define INVALID_FILE_ATTRIBUTES -1 @@ -73,6 +74,90 @@ #include #endif +/* TODO: Some things are duplicated but I'm really afraid of breaking other platforms by touching this */ +#if defined(VITA) +# include +# include +# include +#elif defined(ORBIS) +# include +# include +# include +# include +#elif !defined(_WIN32) +# if defined(PSP) +# include +# endif +# if defined(PS2) +# include +# endif +# include +# include +# include +# include +#endif + +#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) || defined(PS2) +#include /* stat() is defined here */ +#endif + +#ifdef __APPLE__ +#include +#endif +#ifdef __HAIKU__ +#include +#endif +#ifndef __MACH__ +#include +#include +#endif +#include +#include +#include + +#if defined(_WIN32) +#ifndef _XBOX +#if defined(_MSC_VER) && _MSC_VER <= 1200 +#define INVALID_FILE_ATTRIBUTES ((DWORD)-1) +#endif +#endif +#elif defined(VITA) +#define SCE_ERROR_ERRNO_EEXIST 0x80010011 +#include +#include +#include +#else +#include +#include +#include +#endif + +#if defined(ORBIS) +#include +#include +#include +#endif +#if defined(PSP) +#include +#endif + +#if defined(PS2) +#include +#include +#endif + +#if defined(__CELLOS_LV2__) +#include +#endif + +#if defined(VITA) +#define FIO_S_ISDIR SCE_S_ISDIR +#endif + +#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) +#include /* stat() is defined here */ +#endif + /* Assume W-functions do not work below Win2K and Xbox platforms */ #if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX) @@ -99,6 +184,7 @@ #include #include #include +#include #define RFILE_HINT_UNBUFFERED (1 << 8) @@ -712,3 +798,408 @@ const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *strea abort(); return stream->orig_path; } + + +int retro_vfs_stat_impl(const char *path, int32_t *size) +{ + bool is_dir, is_character_special; +#if defined(ORBIS) + return 0; /* for now */ +#endif +#if defined(VITA) || defined(PSP) + SceIoStat buf; + char *tmp = strdup(path); + size_t len = strlen(tmp); + if (tmp[len-1] == '/') + tmp[len-1] = '\0'; + + if (sceIoGetstat(tmp, &buf) < 0) + { + free(tmp); + return 0; + } + free(tmp); +#elif defined(PS2) + iox_stat_t buf; + char *tmp = strdup(path); + size_t len = strlen(tmp); + if (tmp[len-1] == '/') + tmp[len-1] = '\0'; + + if (fileXioGetStat(tmp, &buf) < 0) + { + free(tmp); + return 0; + } + free(tmp); +#elif defined(__CELLOS_LV2__) + CellFsStat buf; + if (cellFsStat(path, &buf) < 0) + return 0; +#elif defined(_WIN32) + DWORD file_info; + struct _stat buf; + char *path_local = NULL; + wchar_t *path_wide = NULL; + + if (!path || !*path) + return 0; + + (void)path_wide; + (void)path_local; + (void)file_info; + +#if defined(LEGACY_WIN32) + path_local = utf8_to_local_string_alloc(path); + file_info = GetFileAttributes(path_local); + + _stat(path_local, &buf); + + if (path_local) + free(path_local); +#else + path_wide = utf8_to_utf16_string_alloc(path); + file_info = GetFileAttributesW(path_wide); + + _wstat(path_wide, &buf); + + if (path_wide) + free(path_wide); +#endif + + if (file_info == INVALID_FILE_ATTRIBUTES) + return 0; +#else + struct stat buf; + if (stat(path, &buf) < 0) + return 0; +#endif + + if (size) +#if defined(PS2) + *size = (int32_t)buf.size; +#else + *size = (int32_t)buf.st_size; +#endif + +#if defined(VITA) || defined(PSP) + is_dir = FIO_S_ISDIR(buf.st_mode); +#elif defined(PS2) + is_dir = FIO_S_ISDIR(buf.mode); +#elif defined(__CELLOS_LV2__) + is_dir = ((buf.st_mode & S_IFMT) == S_IFDIR); +#elif defined(_WIN32) + is_dir = (file_info & FILE_ATTRIBUTE_DIRECTORY); +#else + is_dir = S_ISDIR(buf.st_mode); +#endif + +#if defined(VITA) || defined(PSP) || defined(PS2) || defined(__CELLOS_LV2__) || defined(_WIN32) + is_character_special = false; +#else + is_character_special = S_ISCHR(buf.st_mode); +#endif + + return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0); +} + +static bool path_mkdir_error(int ret) +{ +#if defined(VITA) + return (ret == SCE_ERROR_ERRNO_EEXIST); +#elif defined(PSP) || defined(PS2) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(ORBIS) + return (ret == -1); +#else + return (ret < 0 && errno == EEXIST); +#endif +} + +int retro_vfs_mkdir_impl(const char *dir) +{ +#if defined(_WIN32) +#ifdef LEGACY_WIN32 + int ret = _mkdir(dir); +#else + wchar_t *dirW = utf8_to_utf16_string_alloc(dir); + int ret = -1; + + if (dirW) + { + ret = _wmkdir(dirW); + free(dirW); + } +#endif +#elif defined(IOS) + int ret = mkdir(dir, 0755); +#elif defined(VITA) || defined(PSP) + int ret = sceIoMkdir(dir, 0777); +#elif defined(PS2) + int ret =fileXioMkdir(dir, 0777); +#elif defined(ORBIS) + int ret =orbisMkdir(dir, 0755); +#elif defined(__QNX__) + int ret = mkdir(dir, 0777); +#else + int ret = mkdir(dir, 0750); +#endif + + if (path_mkdir_error(ret)) + return -2; + return ret < 0 ? -1 : 0; +} + +#ifdef VFS_FRONTEND +struct retro_vfs_dir_handle +#else +struct libretro_vfs_implementation_dir +#endif +{ + char* orig_path; +#if defined(_WIN32) +#if defined(LEGACY_WIN32) + WIN32_FIND_DATA entry; +#else + WIN32_FIND_DATAW entry; +#endif + HANDLE directory; + bool next; + char path[PATH_MAX_LENGTH]; +#elif defined(VITA) || defined(PSP) + SceUID directory; + SceIoDirent entry; +#elif defined(PS2) + int directory; + iox_dirent_t entry; +#elif defined(__CELLOS_LV2__) + CellFsErrno error; + int directory; + CellFsDirent entry; +#elif defined(ORBIS) + int directory; + struct dirent entry; +#else + DIR *directory; + const struct dirent *entry; +#endif +}; + +static bool dirent_check_error(libretro_vfs_implementation_dir *rdir) +{ +#if defined(_WIN32) + return (rdir->directory == INVALID_HANDLE_VALUE); +#elif defined(VITA) || defined(PSP) || defined(PS2) || defined(ORBIS) + return (rdir->directory < 0); +#elif defined(__CELLOS_LV2__) + return (rdir->error != CELL_FS_SUCCEEDED); +#else + return !(rdir->directory); +#endif +} + +libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool include_hidden) +{ +#if defined(_WIN32) + char path_buf[1024]; + char *path_local = NULL; + wchar_t *path_wide = NULL; + unsigned path_len; +#endif + libretro_vfs_implementation_dir *rdir; + + /*Reject null or empty string paths*/ + if (!name||(*name==0)) + return NULL; + + /*Allocate RDIR struct. Tidied later with retro_closedir*/ + rdir = (libretro_vfs_implementation_dir*)calloc(1, sizeof(*rdir)); + if (!rdir) + return NULL; + + rdir->orig_path = strdup(name); + +#if defined(_WIN32) + (void)path_wide; + (void)path_local; + + path_buf[0] = '\0'; + path_len = strlen(name); + + /* Non-NT platforms don't like extra slashes in the path */ + if (name[path_len - 1] == '\\') + snprintf(path_buf, sizeof(path_buf), "%s*", name); + else + snprintf(path_buf, sizeof(path_buf), "%s\\*", name); + +#if defined(LEGACY_WIN32) + path_local = utf8_to_local_string_alloc(path_buf); + rdir->directory = FindFirstFile(path_local, &rdir->entry); + + if (path_local) + free(path_local); +#else + path_wide = utf8_to_utf16_string_alloc(path_buf); + rdir->directory = FindFirstFileW(path_wide, &rdir->entry); + + if (path_wide) + free(path_wide); +#endif + +#elif defined(VITA) || defined(PSP) + rdir->directory = sceIoDopen(name); +#elif defined(PS2) + rdir->directory = fileXioDopen(name); +#elif defined(_3DS) + rdir->directory = !string_is_empty(name) ? opendir(name) : NULL; + rdir->entry = NULL; +#elif defined(__CELLOS_LV2__) + rdir->error = cellFsOpendir(name, &rdir->directory); +#elif defined(ORBIS) + rdir->directory = orbisDopen(name); +#else + rdir->directory = opendir(name); + rdir->entry = NULL; +#endif + +#ifdef _WIN32 + if (include_hidden) + rdir->entry.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN; + else + rdir->entry.dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN; +#endif + + if (rdir->directory && !dirent_check_error(rdir)) + return rdir; + + free(rdir); + return NULL; +} + +bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *rdir) +{ +#if defined(_WIN32) + if(rdir->next) +#if defined(LEGACY_WIN32) + return (FindNextFile(rdir->directory, &rdir->entry) != 0); +#else + return (FindNextFileW(rdir->directory, &rdir->entry) != 0); +#endif + + rdir->next = true; + return (rdir->directory != INVALID_HANDLE_VALUE); +#elif defined(VITA) || defined(PSP) + return (sceIoDread(rdir->directory, &rdir->entry) > 0); +#elif defined(PS2) + iox_dirent_t record; + int ret = fileXioDread(rdir->directory, &record); + rdir->entry = record; + return ( ret > 0); +#elif defined(__CELLOS_LV2__) + uint64_t nread; + rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread); + return (nread != 0); +#elif defined(ORBIS) + return (orbisDread(rdir->directory, &rdir->entry) > 0); +#else + return ((rdir->entry = readdir(rdir->directory)) != NULL); +#endif +} + +const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *rdir) +{ +#if defined(_WIN32) +#if defined(LEGACY_WIN32) + char *name_local = local_to_utf8_string_alloc(rdir->entry.cFileName); + memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName)); + strlcpy(rdir->entry.cFileName, name_local, sizeof(rdir->entry.cFileName)); + + if (name_local) + free(name_local); +#else + char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName); + memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName)); + strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName)); + + if (name) + free(name); +#endif + return (char*)rdir->entry.cFileName; +#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(ORBIS) + return rdir->entry.d_name; +#elif defined(PS2) + return rdir->entry.name; +#else + + return rdir->entry->d_name; +#endif +} + +bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir) +{ +#if defined(_WIN32) + const WIN32_FIND_DATA *entry = (const WIN32_FIND_DATA*)&rdir->entry; + return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; +#elif defined(PSP) || defined(VITA) + const SceIoDirent *entry = (const SceIoDirent*)&rdir->entry; +#if defined(PSP) + return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR; +#elif defined(VITA) + return SCE_S_ISDIR(entry->d_stat.st_mode); +#endif +#elif defined(PS2) + const iox_dirent_t *entry = (const iox_dirent_t*)&rdir->entry; + return FIO_S_ISDIR(entry->stat.mode); +#elif defined(__CELLOS_LV2__) + CellFsDirent *entry = (CellFsDirent*)&rdir->entry; + return (entry->d_type == CELL_FS_TYPE_DIRECTORY); +#elif defined(ORBIS) + const struct dirent *entry = &rdir->entry; + if (entry->d_type==DT_DIR) + return true; + if (!(entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK)) + return false; +#else + struct stat buf; +#if defined(DT_DIR) + const struct dirent *entry = (const struct dirent*)rdir->entry; + if (entry->d_type == DT_DIR) + return true; + /* This can happen on certain file systems. */ + if (!(entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK)) + return false; +#endif + /* dirent struct doesn't have d_type, do it the slow way ... */ + char path[PATH_MAX_LENGTH]; + path[0] = '\0'; + fill_pathname_join(path, rdir->orig_path, retro_vfs_dirent_get_name_impl(rdir), sizeof(path)); + if (stat(path, &buf) < 0) + return false; + return S_ISDIR(buf.st_mode); +#endif +} + +int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir) +{ + if (!rdir) + return -1; + +#if defined(_WIN32) + if (rdir->directory != INVALID_HANDLE_VALUE) + FindClose(rdir->directory); +#elif defined(VITA) || defined(PSP) + sceIoDclose(rdir->directory); +#elif defined(PS2) + fileXioDclose(rdir->directory); +#elif defined(__CELLOS_LV2__) + rdir->error = cellFsClosedir(rdir->directory); +#elif defined(ORBIS) + orbisDclose(rdir->directory); +#else + if (rdir->directory) + closedir(rdir->directory); +#endif + + if (rdir->orig_path) + free(rdir->orig_path); + free(rdir); + return 0; +} From 5a97738f3e18f3c86508fc3a6f035b221a974d74 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Wed, 16 Jan 2019 21:01:37 +0100 Subject: [PATCH 2/4] Revert "Revert "Cleanups"" This reverts commit 5c2d271f9f6bdb2ebf0528cb5a611634efe11b86. --- libretro-common/file/file_path.c | 6 ++---- libretro-common/file/retro_dirent.c | 12 ++++-------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/libretro-common/file/file_path.c b/libretro-common/file/file_path.c index 07b19e67fe..8d9eb8a73c 100644 --- a/libretro-common/file/file_path.c +++ b/libretro-common/file/file_path.c @@ -142,16 +142,14 @@ static int path_stat(const char *path, int32_t *size) { if (path_stat_cb != NULL) return path_stat_cb(path, NULL); - else - return retro_vfs_stat_impl(path, NULL); + return retro_vfs_stat_impl(path, NULL); } static int path_mkdir_norecurse(const char *dir) { if (path_mkdir_cb != NULL) return path_mkdir_cb(dir); - else - return retro_vfs_mkdir_impl(dir); + return retro_vfs_mkdir_impl(dir); } /** diff --git a/libretro-common/file/retro_dirent.c b/libretro-common/file/retro_dirent.c index 353a12e81b..752cbdad01 100644 --- a/libretro-common/file/retro_dirent.c +++ b/libretro-common/file/retro_dirent.c @@ -63,8 +63,7 @@ struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden) { if (dirent_opendir_cb != NULL) return (struct RDIR *)dirent_opendir_cb(name, include_hidden); - else - return (struct RDIR *)retro_vfs_opendir_impl(name, include_hidden); + return (struct RDIR *)retro_vfs_opendir_impl(name, include_hidden); } struct RDIR *retro_opendir(const char *name) @@ -82,16 +81,14 @@ int retro_readdir(struct RDIR *rdir) { if (dirent_readdir_cb != NULL) return dirent_readdir_cb((struct retro_vfs_dir_handle *)rdir); - else - return retro_vfs_readdir_impl((struct retro_vfs_dir_handle *)rdir); + return retro_vfs_readdir_impl((struct retro_vfs_dir_handle *)rdir); } const char *retro_dirent_get_name(struct RDIR *rdir) { if (dirent_dirent_get_name_cb != NULL) return dirent_dirent_get_name_cb((struct retro_vfs_dir_handle *)rdir); - else - return retro_vfs_dirent_get_name_impl((struct retro_vfs_dir_handle *)rdir); + return retro_vfs_dirent_get_name_impl((struct retro_vfs_dir_handle *)rdir); } /** @@ -109,8 +106,7 @@ bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused) { if (dirent_dirent_is_dir_cb != NULL) return dirent_dirent_is_dir_cb((struct retro_vfs_dir_handle *)rdir); - else - return retro_vfs_dirent_is_dir_impl((struct retro_vfs_dir_handle *)rdir); + return retro_vfs_dirent_is_dir_impl((struct retro_vfs_dir_handle *)rdir); } void retro_closedir(struct RDIR *rdir) From f93ae772f3eb2f43c0a70eb1a9722d3794d271f7 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Wed, 16 Jan 2019 21:03:15 +0100 Subject: [PATCH 3/4] Fix error in path_get_size --- libretro-common/file/file_path.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libretro-common/file/file_path.c b/libretro-common/file/file_path.c index 8d9eb8a73c..27f96f34bb 100644 --- a/libretro-common/file/file_path.c +++ b/libretro-common/file/file_path.c @@ -141,8 +141,8 @@ void path_vfs_init(const struct retro_vfs_interface_info* vfs_info) static int path_stat(const char *path, int32_t *size) { if (path_stat_cb != NULL) - return path_stat_cb(path, NULL); - return retro_vfs_stat_impl(path, NULL); + return path_stat_cb(path, size); + return retro_vfs_stat_impl(path, size); } static int path_mkdir_norecurse(const char *dir) From f011579c7804a9578beac103e4f4c898a08b863d Mon Sep 17 00:00:00 2001 From: krzys-h Date: Wed, 16 Jan 2019 21:21:49 +0100 Subject: [PATCH 4/4] Fix memory leak when opening non-existent directories --- libretro-common/vfs/vfs_implementation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libretro-common/vfs/vfs_implementation.c b/libretro-common/vfs/vfs_implementation.c index 693ecfd748..0fbd7875e4 100644 --- a/libretro-common/vfs/vfs_implementation.c +++ b/libretro-common/vfs/vfs_implementation.c @@ -1070,7 +1070,7 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i if (rdir->directory && !dirent_check_error(rdir)) return rdir; - free(rdir); + retro_vfs_closedir_impl(rdir); return NULL; }