From a549e28f0101cf42b6ee6ef4834ddcf983f0b448 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Wed, 16 Jan 2019 03:53:34 +0100 Subject: [PATCH] Revert "VFS v3: stat, mkdir, directory listings" --- 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, 441 insertions(+), 702 deletions(-) diff --git a/dynamic.c b/dynamic.c index a6d3074013..d00ea50160 100644 --- a/dynamic.c +++ b/dynamic.c @@ -1927,10 +1927,9 @@ bool rarch_environment_cb(unsigned cmd, void *data) case RETRO_ENVIRONMENT_GET_VFS_INTERFACE: { - const uint32_t supported_vfs_version = 3; + const uint32_t supported_vfs_version = 1; 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, @@ -1940,32 +1939,15 @@ 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_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 + retro_vfs_file_remove_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 07b19e67fe..c2d9459908 100644 --- a/libretro-common/file/file_path.c +++ b/libretro-common/file/file_path.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2019 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_path.c). @@ -32,10 +32,7 @@ #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 @@ -119,39 +116,118 @@ #endif -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) +enum stat_mode { - const struct retro_vfs_interface* vfs_iface; + IS_DIRECTORY = 0, + IS_CHARACTER_SPECIAL, + IS_VALID +}; - 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) +static bool path_stat(const char *path, enum stat_mode mode, int32_t *size) { - if (path_stat_cb != NULL) - return path_stat_cb(path, NULL); - else - return retro_vfs_stat_impl(path, NULL); -} +#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'; -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); + 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; } /** @@ -165,7 +241,6 @@ static int path_mkdir_norecurse(const char *dir) bool path_is_directory(const char *path) { #ifdef ORBIS - /* TODO: This should be moved to the VFS module */ int dfd; if (!path) return false; @@ -175,29 +250,40 @@ bool path_is_directory(const char *path) orbisDclose(dfd); return true; #else - return (path_stat(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0; + return path_stat(path, IS_DIRECTORY, NULL); #endif } bool path_is_character_special(const char *path) { - return (path_stat(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0; + return path_stat(path, IS_CHARACTER_SPECIAL, NULL); } bool path_is_valid(const char *path) { - return (path_stat(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0; + return path_stat(path, IS_VALID, NULL); } int32_t path_get_size(const char *path) { int32_t filesize = 0; - if (path_stat(path, &filesize) != 0) + if (path_stat(path, IS_VALID, &filesize)) 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 @@ -243,10 +329,35 @@ bool path_mkdir(const char *dir) if (norecurse) { - int ret = path_mkdir_norecurse(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 /* Don't treat this as an error. */ - if (ret == -2 && path_is_directory(dir)) + if (path_mkdir_error(ret) && 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 353a12e81b..bf11e06654 100644 --- a/libretro-common/file/retro_dirent.c +++ b/libretro-common/file/retro_dirent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2019 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_dirent.c). @@ -28,95 +28,313 @@ #include #include -#define VFS_FRONTEND -#include +#include +#include +#include -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; +#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 -void dirent_vfs_init(const struct retro_vfs_interface_info* vfs_info) +#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 { - 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); -} +#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 +}; struct RDIR *retro_opendir(const char *name) { - return retro_opendir_include_hidden(name, false); +#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; } bool retro_dirent_error(struct RDIR *rdir) { - /* Left for compatibility */ - return false; +#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 } 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); +#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_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); +#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 } /** * * retro_dirent_is_dir: * @rdir : pointer to the directory entry. - * @unused : deprecated, included for compatibility reasons, pass NULL + * @path : path to the directory entry. * * 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 *unused) +bool retro_dirent_is_dir(struct RDIR *rdir, const char *path) { - if (dirent_dirent_is_dir_cb != NULL) - return dirent_dirent_is_dir_cb((struct retro_vfs_dir_handle *)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 ... */ + 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; else - return retro_vfs_dirent_is_dir_impl((struct retro_vfs_dir_handle *)rdir); + rdir->entry.dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN; +#endif } void retro_closedir(struct RDIR *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); + 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); } diff --git a/libretro-common/include/file/file_path.h b/libretro-common/include/file/file_path.h index e894bebdc3..c6896e05ab 100644 --- a/libretro-common/include/file/file_path.h +++ b/libretro-common/include/file/file_path.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2019 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_path.h). @@ -28,17 +28,12 @@ #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 2f077c5522..4e1a9785ba 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -1100,10 +1100,6 @@ 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 */ @@ -1123,12 +1119,6 @@ struct retro_vfs_dir_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); @@ -1138,7 +1128,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 success, -1 on failure. +/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on succes, -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); @@ -1151,7 +1141,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); @@ -1179,39 +1169,6 @@ 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 */ @@ -1228,14 +1185,6 @@ 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 8a2591bd3a..c3450732c5 100644 --- a/libretro-common/include/retro_dirent.h +++ b/libretro-common/include/retro_dirent.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2019 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_dirent.h). @@ -23,7 +23,6 @@ #ifndef __RETRO_DIRENT_H #define __RETRO_DIRENT_H -#include #include #include @@ -31,10 +30,6 @@ 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; /** @@ -49,27 +44,25 @@ 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 *unused); +bool retro_dirent_is_dir(struct RDIR *rdir, const char *path); 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 afc2e22213..5a1e5c3a9c 100644 --- a/libretro-common/include/vfs/vfs_implementation.h +++ b/libretro-common/include/vfs/vfs_implementation.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2019 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vfs_implementation.h). @@ -38,12 +38,6 @@ 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); @@ -70,18 +64,4 @@ 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 6afc3fab30..0972ec84f0 100644 --- a/libretro-common/lists/dir_list.c +++ b/libretro-common/lists/dir_list.c @@ -171,11 +171,13 @@ static int dir_list_read(const char *dir, bool include_dirs, bool include_hidden, bool include_compressed, bool recursive) { - struct RDIR *entry = retro_opendir_include_hidden(dir, include_hidden); + struct RDIR *entry = retro_opendir(dir); 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]; @@ -187,7 +189,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, NULL); + is_dir = retro_dirent_is_dir(entry, file_path); 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 693ecfd748..c2232fd6c5 100644 --- a/libretro-common/vfs/vfs_implementation.c +++ b/libretro-common/vfs/vfs_implementation.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2019 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (vfs_implementation.c). @@ -34,7 +34,6 @@ # ifdef _MSC_VER # define setmode _setmode # endif -#include # ifdef _XBOX # include # define INVALID_FILE_ATTRIBUTES -1 @@ -74,90 +73,6 @@ #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) @@ -184,7 +99,6 @@ #include #include #include -#include #define RFILE_HINT_UNBUFFERED (1 << 8) @@ -798,408 +712,3 @@ 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; -}