Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 30 additions & 10 deletions libretro-common/file/file_path_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,35 @@
#endif

/* TODO/FIXME - globals */
static retro_vfs_stat_t path_stat_cb = retro_vfs_stat_impl;
static retro_vfs_stat_t path_stat32_cb = retro_vfs_stat_impl;
static retro_vfs_stat_64_t path_stat64_cb = retro_vfs_stat_64_impl;
static retro_vfs_mkdir_t path_mkdir_cb = retro_vfs_mkdir_impl;

void path_vfs_init(const struct retro_vfs_interface_info* vfs_info)
{
const struct retro_vfs_interface*
vfs_iface = vfs_info->iface;

path_stat_cb = retro_vfs_stat_impl;
path_stat32_cb = retro_vfs_stat_impl;
path_stat64_cb = retro_vfs_stat_64_impl;
path_mkdir_cb = retro_vfs_mkdir_impl;

if (vfs_info->required_interface_version < PATH_REQUIRED_VFS_VERSION || !vfs_iface)
return;

path_stat_cb = vfs_iface->stat;
path_stat32_cb = vfs_iface->stat;
path_mkdir_cb = vfs_iface->mkdir;

if (vfs_info->required_interface_version >= STAT64_REQUIRED_VFS_VERSION)
path_stat64_cb = vfs_iface->stat_64;
else
path_stat64_cb = NULL;
}

int path_stat(const char *path)
{
return path_stat_cb(path, NULL);
/* Use 64‑bit stat if available, else fallback */
return path_stat64_cb ? path_stat64_cb(path, NULL) : path_stat32_cb(path, NULL);
}

/**
Expand All @@ -76,25 +84,37 @@ int path_stat(const char *path)
*/
bool path_is_directory(const char *path)
{
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
if (path_stat64_cb)
return (path_stat64_cb(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
return (path_stat32_cb(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
}

bool path_is_character_special(const char *path)
{
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
if (path_stat64_cb)
return (path_stat64_cb(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
return (path_stat32_cb(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
}

bool path_is_valid(const char *path)
{
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
if (path_stat64_cb)
return (path_stat64_cb(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
return (path_stat32_cb(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
}

int32_t path_get_size(const char *path)
int64_t path_get_size(const char *path)
{
int32_t filesize = 0;
if (path_stat_cb(path, &filesize) != 0)
int64_t filesize = 0;
int32_t filesize32 = 0;

if (path_stat64_cb && path_stat64_cb(path, &filesize) != 0)
return filesize;

/* Fallback: 32-bit stat */
if (path_stat32_cb && path_stat32_cb(path, &filesize32) != 0)
return (int64_t)filesize32;

return -1;
}

Expand Down
2 changes: 1 addition & 1 deletion libretro-common/formats/logiqx_dat/logiqx_dat.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const char *logiqx_dat_html_code_list[][2] = {
bool logiqx_dat_path_is_valid(const char *path, uint64_t *file_size)
{
const char *file_ext = NULL;
int32_t file_size_int;
int64_t file_size_int;

if (string_is_empty(path))
return false;
Expand Down
3 changes: 2 additions & 1 deletion libretro-common/include/file/file_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
RETRO_BEGIN_DECLS

#define PATH_REQUIRED_VFS_VERSION 3
#define STAT64_REQUIRED_VFS_VERSION 4

void path_vfs_init(const struct retro_vfs_interface_info* vfs_info);

Expand Down Expand Up @@ -681,7 +682,7 @@ int path_stat(const char *path);

bool path_is_valid(const char *path);

int32_t path_get_size(const char *path);
int64_t path_get_size(const char *path);

bool is_path_accessible_using_standard_io(const char *path);

Expand Down
17 changes: 17 additions & 0 deletions libretro-common/include/libretro.h
Original file line number Diff line number Diff line change
Expand Up @@ -2923,6 +2923,19 @@ typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const cha
*/
typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size);

/**
* Gets information about the given file (64-bit size).
*
* @param path The path to the file to query.
* @param[out] size The reported size of the file in bytes.
* May be \c NULL, in which case this value is ignored.
* @return A bitmask of \c RETRO_VFS_STAT flags,
* or 0 if \c path doesn't refer to a valid file.
* @see RETRO_VFS_STAT
* @since VFS API v4
*/
typedef int (RETRO_CALLCONV *retro_vfs_stat_64_t)(const char *path, int64_t *size);

/**
* Creates a directory at the given path.
*
Expand Down Expand Up @@ -3078,6 +3091,10 @@ struct retro_vfs_interface

/** @copydoc retro_vfs_closedir_t */
retro_vfs_closedir_t closedir;

/* VFS API v4 */
/** @copydoc retro_vfs_stat_64_t */
retro_vfs_stat_64_t stat_64;
};

/**
Expand Down
2 changes: 2 additions & 0 deletions libretro-common/include/vfs/vfs_implementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *strea

int retro_vfs_stat_impl(const char *path, int32_t *size);

int retro_vfs_stat_64_impl(const char *path, int64_t *size);

int retro_vfs_mkdir_impl(const char *dir);

libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *dir, bool include_hidden);
Expand Down
2 changes: 1 addition & 1 deletion libretro-common/include/vfs/vfs_implementation_saf.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ int retro_vfs_file_remove_saf(const char *tree, const char *path);

int retro_vfs_file_rename_saf(const char *old_tree, const char *old_path, const char *new_tree, const char *new_path);

int retro_vfs_stat_saf(const char *tree, const char *path, int32_t *size);
int retro_vfs_stat_saf(const char *tree, const char *path, int64_t *size);

int retro_vfs_mkdir_saf(const char *tree, const char *dir);

Expand Down
40 changes: 31 additions & 9 deletions libretro-common/vfs/vfs_implementation.c
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ const char *retro_vfs_file_get_path_impl(
return stream->orig_path;
}

int retro_vfs_stat_impl(const char *path, int32_t *size)
int retro_vfs_stat_64_impl(const char *path, int64_t *size)
{
int ret = RETRO_VFS_STAT_IS_VALID;

Expand Down Expand Up @@ -1088,7 +1088,7 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
return 0;

if (size)
*size = (int32_t)stat_buf.st_size;
*size = (int64_t)stat_buf.st_size;

if (FIO_S_ISDIR(stat_buf.st_mode))
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
Expand All @@ -1100,14 +1100,15 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
return 0;

if (size)
*size = (int32_t)stat_buf.st_size;
*size = (int64_t)stat_buf.st_size;

if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
#elif defined(_WIN32)
/* Windows */
struct _stat stat_buf;
struct _stat64 stat_buf;
#if defined(LEGACY_WIN32)
/* 32-bit only */
char *path_local = utf8_to_local_string_alloc(path);
DWORD file_info = GetFileAttributes(path_local);

Expand All @@ -1120,7 +1121,7 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
wchar_t *path_wide = utf8_to_utf16_string_alloc(path);
DWORD file_info = GetFileAttributesW(path_wide);

_wstat(path_wide, &stat_buf);
_wstat64(path_wide, &stat_buf);

if (path_wide)
free(path_wide);
Expand All @@ -1129,7 +1130,7 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
return 0;

if (size)
*size = (int32_t)stat_buf.st_size;
*size = (int64_t)stat_buf.st_size;

if (file_info & FILE_ATTRIBUTE_DIRECTORY)
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
Expand Down Expand Up @@ -1157,21 +1158,27 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
free(path_buf);

if (size)
*size = (int32_t)stat_buf.st_size;
*size = (int64_t)stat_buf.st_size;

if (S_ISDIR(stat_buf.st_mode))
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
if (S_ISCHR(stat_buf.st_mode))
ret |= RETRO_VFS_STAT_IS_CHARACTER_SPECIAL;
#else
/* Every other platform */
#if defined(_LARGEFILE64_SOURCE)
struct stat64 stat_buf;
if (stat64(path, &stat_buf) < 0)
return 0;
#else
struct stat stat_buf;

if (stat(path, &stat_buf) < 0)
return 0;
#endif

if (size)
*size = (int32_t)stat_buf.st_size;
*size = (int64_t)stat_buf.st_size;

if (S_ISDIR(stat_buf.st_mode))
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
Expand All @@ -1182,6 +1189,21 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
return ret;
}

int retro_vfs_stat_impl(const char *path, int32_t *size)
{
int64_t size64 = 0;
int ret = retro_vfs_stat_64_impl(path, size ? &size64 : NULL);

/* if a file is larger than 2 GB, size64 will hold the correct value
* but the cast to int32_t will truncate it.
* new code should migrate to retro_vfs_stat_64_t
*/
if (size)
*size = (int32_t)size64;

return ret;
}

#if defined(VITA)
#define path_mkdir_err(ret) (((ret) == SCE_ERROR_ERRNO_EEXIST))
#elif defined(PSP) || defined(PS2) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
Expand Down Expand Up @@ -1523,7 +1545,7 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir)
{
char full[PATH_MAX_LENGTH];
const char *name = retro_vfs_dirent_get_name_impl(rdir);
int32_t sz = 0;
int64_t sz = 0;
int st = 0;

if (!name)
Expand Down
4 changes: 2 additions & 2 deletions libretro-common/vfs/vfs_implementation_saf.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ int retro_vfs_file_rename_saf(const char *old_tree, const char *old_path, const
return -1;
}

int retro_vfs_stat_saf(const char *tree, const char *path, int32_t *size)
int retro_vfs_stat_saf(const char *tree, const char *path, int64_t *size)
{
JNIEnv *env;
jstring tree_object;
Expand Down Expand Up @@ -515,7 +515,7 @@ int retro_vfs_stat_saf(const char *tree, const char *path, int32_t *size)
if ((*env)->ExceptionOccurred(env)) goto error;

if (size != NULL)
*size = saf_stat_size > INT32_MAX ? INT32_MAX : (int32_t)saf_stat_size;
*size = saf_stat_size > INT64_MAX ? INT64_MAX : (int64_t)saf_stat_size;

(*env)->PopLocalFrame(env, NULL);
return saf_stat_is_directory ? RETRO_VFS_STAT_IS_VALID | RETRO_VFS_STAT_IS_DIRECTORY : RETRO_VFS_STAT_IS_VALID;
Expand Down
4 changes: 2 additions & 2 deletions libretro-common/vfs/vfs_implementation_smb.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ int retro_vfs_closedir_smb(smb_dir_handle* dh)
return 0;
}

int retro_vfs_stat_smb(const char *path, int32_t *size)
int retro_vfs_stat_smb(const char *path, int64_t *size)
{
char rel_path[PATH_MAX_LENGTH];
struct smb2_stat_64 st;
Expand Down Expand Up @@ -572,7 +572,7 @@ int retro_vfs_stat_smb(const char *path, int32_t *size)
return 0;

if (size)
*size = (int32_t)st.smb2_size;
*size = (int64_t)st.smb2_size;

return RETRO_VFS_STAT_IS_VALID |
(st.smb2_type == SMB2_TYPE_DIRECTORY ? RETRO_VFS_STAT_IS_DIRECTORY : 0);
Expand Down
2 changes: 1 addition & 1 deletion libretro-common/vfs/vfs_implementation_smb.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct smbc_dirent* retro_vfs_readdir_smb(smb_dir_handle* dh);
int retro_vfs_closedir_smb(smb_dir_handle* dh);

/* Stat */
int retro_vfs_stat_smb(const char *path, int32_t *size);
int retro_vfs_stat_smb(const char *path, int64_t *size);

/* Errors */
int retro_vfs_file_error_smb(libretro_vfs_implementation_file *stream);
Expand Down
19 changes: 17 additions & 2 deletions libretro-common/vfs/vfs_implementation_uwp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *strea
return stream->orig_path;
}

int retro_vfs_stat_impl(const char *path, int32_t *size)
int retro_vfs_stat_64_impl(const char *path, int64_t *size)
{
wchar_t *path_wide;
_WIN32_FILE_ATTRIBUTE_DATA attribdata;
Expand Down Expand Up @@ -699,6 +699,21 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
return 0;
}

int retro_vfs_stat_impl(const char *path, int32_t *size)
{
int64_t size64 = 0;
int ret = retro_vfs_stat_64_impl(path, size ? &size64 : NULL);

/* if a file is larger than 2 GB, size64 will hold the correct value
* but the cast to int32_t will truncate it.
* new code should migrate to retro_vfs_stat_64_t
*/
if (size)
*size = (int32_t)size64;

return ret;
}

#ifdef VFS_FRONTEND
struct retro_vfs_dir_handle
#else
Expand Down Expand Up @@ -832,7 +847,7 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir* rdir)
return false;

fill_pathname_join_special(full, rdir->orig_path, name, sizeof(full));
int32_t sz = 0;
int64_t sz = 0;
int st = retro_vfs_stat_smb(full, &sz);

return (st & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
Expand Down
6 changes: 4 additions & 2 deletions runloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -3044,7 +3044,7 @@ bool runloop_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 = 4;
static struct retro_vfs_interface vfs_iface =
{
/* VFS API v1 */
Expand All @@ -3068,7 +3068,9 @@ bool runloop_environment_cb(unsigned cmd, void *data)
retro_vfs_readdir_impl,
retro_vfs_dirent_get_name_impl,
retro_vfs_dirent_is_dir_impl,
retro_vfs_closedir_impl
retro_vfs_closedir_impl,
/* VFS API v4 */
retro_vfs_stat_64_impl,
};

struct retro_vfs_interface_info *vfs_iface_info = (struct retro_vfs_interface_info *) data;
Expand Down
Loading