Skip to content

Commit ee3eae3

Browse files
authored
vfs: add retro_vfs_stat64_t (#18633)
1 parent 4e6cb4b commit ee3eae3

12 files changed

Lines changed: 109 additions & 31 deletions

libretro-common/file/file_path_io.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,35 @@
4242
#endif
4343

4444
/* TODO/FIXME - globals */
45-
static retro_vfs_stat_t path_stat_cb = retro_vfs_stat_impl;
45+
static retro_vfs_stat_t path_stat32_cb = retro_vfs_stat_impl;
46+
static retro_vfs_stat_64_t path_stat64_cb = retro_vfs_stat_64_impl;
4647
static retro_vfs_mkdir_t path_mkdir_cb = retro_vfs_mkdir_impl;
4748

4849
void path_vfs_init(const struct retro_vfs_interface_info* vfs_info)
4950
{
5051
const struct retro_vfs_interface*
5152
vfs_iface = vfs_info->iface;
5253

53-
path_stat_cb = retro_vfs_stat_impl;
54+
path_stat32_cb = retro_vfs_stat_impl;
55+
path_stat64_cb = retro_vfs_stat_64_impl;
5456
path_mkdir_cb = retro_vfs_mkdir_impl;
5557

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

59-
path_stat_cb = vfs_iface->stat;
61+
path_stat32_cb = vfs_iface->stat;
6062
path_mkdir_cb = vfs_iface->mkdir;
63+
64+
if (vfs_info->required_interface_version >= STAT64_REQUIRED_VFS_VERSION)
65+
path_stat64_cb = vfs_iface->stat_64;
66+
else
67+
path_stat64_cb = NULL;
6168
}
6269

6370
int path_stat(const char *path)
6471
{
65-
return path_stat_cb(path, NULL);
72+
/* Use 64‑bit stat if available, else fallback */
73+
return path_stat64_cb ? path_stat64_cb(path, NULL) : path_stat32_cb(path, NULL);
6674
}
6775

6876
/**
@@ -75,25 +83,37 @@ int path_stat(const char *path)
7583
*/
7684
bool path_is_directory(const char *path)
7785
{
78-
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
86+
if (path_stat64_cb)
87+
return (path_stat64_cb(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
88+
return (path_stat32_cb(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
7989
}
8090

8191
bool path_is_character_special(const char *path)
8292
{
83-
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
93+
if (path_stat64_cb)
94+
return (path_stat64_cb(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
95+
return (path_stat32_cb(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
8496
}
8597

8698
bool path_is_valid(const char *path)
8799
{
88-
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
100+
if (path_stat64_cb)
101+
return (path_stat64_cb(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
102+
return (path_stat32_cb(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
89103
}
90104

91-
int32_t path_get_size(const char *path)
105+
int64_t path_get_size(const char *path)
92106
{
93-
int32_t filesize = 0;
94-
if (path_stat_cb(path, &filesize) != 0)
107+
int64_t filesize = 0;
108+
int32_t filesize32 = 0;
109+
110+
if (path_stat64_cb && path_stat64_cb(path, &filesize) != 0)
95111
return filesize;
96112

113+
/* Fallback: 32-bit stat */
114+
if (path_stat32_cb && path_stat32_cb(path, &filesize32) != 0)
115+
return (int64_t)filesize32;
116+
97117
return -1;
98118
}
99119

libretro-common/formats/logiqx_dat/logiqx_dat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const char *logiqx_dat_html_code_list[][2] = {
5757
bool logiqx_dat_path_is_valid(const char *path, uint64_t *file_size)
5858
{
5959
const char *file_ext = NULL;
60-
int32_t file_size_int;
60+
int64_t file_size_int;
6161

6262
if (!path || !*path)
6363
return false;

libretro-common/include/file/file_path.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
RETRO_BEGIN_DECLS
3737

3838
#define PATH_REQUIRED_VFS_VERSION 3
39+
#define STAT64_REQUIRED_VFS_VERSION 4
3940

4041
void path_vfs_init(const struct retro_vfs_interface_info* vfs_info);
4142

@@ -677,7 +678,7 @@ int path_stat(const char *path);
677678

678679
bool path_is_valid(const char *path);
679680

680-
int32_t path_get_size(const char *path);
681+
int64_t path_get_size(const char *path);
681682

682683
bool is_path_accessible_using_standard_io(const char *path);
683684

libretro-common/include/libretro.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2936,6 +2936,19 @@ typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const cha
29362936
*/
29372937
typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size);
29382938

2939+
/**
2940+
* Gets information about the given file (64-bit size).
2941+
*
2942+
* @param path The path to the file to query.
2943+
* @param[out] size The reported size of the file in bytes.
2944+
* May be \c NULL, in which case this value is ignored.
2945+
* @return A bitmask of \c RETRO_VFS_STAT flags,
2946+
* or 0 if \c path doesn't refer to a valid file.
2947+
* @see RETRO_VFS_STAT
2948+
* @since VFS API v4
2949+
*/
2950+
typedef int (RETRO_CALLCONV *retro_vfs_stat_64_t)(const char *path, int64_t *size);
2951+
29392952
/**
29402953
* Creates a directory at the given path.
29412954
*
@@ -3091,6 +3104,10 @@ struct retro_vfs_interface
30913104

30923105
/** @copydoc retro_vfs_closedir_t */
30933106
retro_vfs_closedir_t closedir;
3107+
3108+
/* VFS API v4 */
3109+
/** @copydoc retro_vfs_stat_64_t */
3110+
retro_vfs_stat_64_t stat_64;
30943111
};
30953112

30963113
/**

libretro-common/include/vfs/vfs_implementation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *strea
5959

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

62+
int retro_vfs_stat_64_impl(const char *path, int64_t *size);
63+
6264
int retro_vfs_mkdir_impl(const char *dir);
6365

6466
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *dir, bool include_hidden);

libretro-common/include/vfs/vfs_implementation_saf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ int retro_vfs_file_remove_saf(const char *tree, const char *path);
9191

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

94-
int retro_vfs_stat_saf(const char *tree, const char *path, int32_t *size);
94+
int retro_vfs_stat_saf(const char *tree, const char *path, int64_t *size);
9595

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

libretro-common/vfs/vfs_implementation.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ const char *retro_vfs_file_get_path_impl(
10071007
return stream->orig_path;
10081008
}
10091009

1010-
int retro_vfs_stat_impl(const char *path, int32_t *size)
1010+
int retro_vfs_stat_64_impl(const char *path, int64_t *size)
10111011
{
10121012
int ret = RETRO_VFS_STAT_IS_VALID;
10131013

@@ -1047,7 +1047,7 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
10471047
return 0;
10481048

10491049
if (size)
1050-
*size = (int32_t)stat_buf.st_size;
1050+
*size = (int64_t)stat_buf.st_size;
10511051

10521052
if (FIO_S_ISDIR(stat_buf.st_mode))
10531053
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
@@ -1059,15 +1059,15 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
10591059
return 0;
10601060

10611061
if (size)
1062-
*size = (int32_t)stat_buf.st_size;
1062+
*size = (int64_t)stat_buf.st_size;
10631063

10641064
if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)
10651065
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
10661066
#elif defined(_WIN32)
10671067
/* Windows
10681068
* Older MSVC _stat may fail on directory paths
10691069
* with a trailing backslash */
1070-
struct _stat stat_buf;
1070+
struct _stat64 stat_buf;
10711071
char path_buf[PATH_MAX_LENGTH];
10721072
const char *stat_path = path;
10731073
DWORD file_info;
@@ -1120,7 +1120,7 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
11201120
file_info = GetFileAttributesW(path_wide);
11211121

11221122
if (file_info == INVALID_FILE_ATTRIBUTES
1123-
|| _wstat(path_wide, &stat_buf) != 0)
1123+
|| _wstat64(path_wide, &stat_buf) != 0)
11241124
{
11251125
free(path_wide);
11261126
return 0;
@@ -1130,7 +1130,7 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
11301130
#endif
11311131

11321132
if (size)
1133-
*size = (int32_t)stat_buf.st_size;
1133+
*size = (int64_t)stat_buf.st_size;
11341134

11351135
if (file_info & FILE_ATTRIBUTE_DIRECTORY)
11361136
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
@@ -1150,21 +1150,27 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
11501150
return 0;
11511151

11521152
if (size)
1153-
*size = (int32_t)stat_buf.st_size;
1153+
*size = (int64_t)stat_buf.st_size;
11541154

11551155
if (S_ISDIR(stat_buf.st_mode))
11561156
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
11571157
if (S_ISCHR(stat_buf.st_mode))
11581158
ret |= RETRO_VFS_STAT_IS_CHARACTER_SPECIAL;
11591159
#else
11601160
/* Every other platform */
1161+
#if defined(_LARGEFILE64_SOURCE)
1162+
struct stat64 stat_buf;
1163+
if (stat64(path, &stat_buf) < 0)
1164+
return 0;
1165+
#else
11611166
struct stat stat_buf;
11621167

11631168
if (stat(path, &stat_buf) < 0)
11641169
return 0;
1170+
#endif
11651171

11661172
if (size)
1167-
*size = (int32_t)stat_buf.st_size;
1173+
*size = (int64_t)stat_buf.st_size;
11681174

11691175
if (S_ISDIR(stat_buf.st_mode))
11701176
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
@@ -1175,6 +1181,21 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
11751181
return ret;
11761182
}
11771183

1184+
int retro_vfs_stat_impl(const char *path, int32_t *size)
1185+
{
1186+
int64_t size64 = 0;
1187+
int ret = retro_vfs_stat_64_impl(path, size ? &size64 : NULL);
1188+
1189+
/* if a file is larger than 2 GB, size64 will hold the correct value
1190+
* but the cast to int32_t will truncate it.
1191+
* new code should migrate to retro_vfs_stat_64_t
1192+
*/
1193+
if (size)
1194+
*size = (int32_t)size64;
1195+
1196+
return ret;
1197+
}
1198+
11781199
#if defined(VITA)
11791200
#define path_mkdir_err(ret) (((ret) == SCE_ERROR_ERRNO_EEXIST))
11801201
#elif defined(PSP) || defined(PS2) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
@@ -1498,7 +1519,7 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir)
14981519
{
14991520
char full[PATH_MAX_LENGTH];
15001521
const char *name = retro_vfs_dirent_get_name_impl(rdir);
1501-
int32_t sz = 0;
1522+
int64_t sz = 0;
15021523
int st = 0;
15031524

15041525
if (!name)

libretro-common/vfs/vfs_implementation_saf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ int retro_vfs_file_rename_saf(const char *old_tree, const char *old_path, const
620620
return -1;
621621
}
622622

623-
int retro_vfs_stat_saf(const char *tree, const char *path, int32_t *size)
623+
int retro_vfs_stat_saf(const char *tree, const char *path, int64_t *size)
624624
{
625625
JNIEnv *env;
626626
jstring tree_object;
@@ -677,7 +677,7 @@ int retro_vfs_stat_saf(const char *tree, const char *path, int32_t *size)
677677
if ((*env)->ExceptionOccurred(env)) goto error;
678678

679679
if (size != NULL)
680-
*size = saf_stat_size > INT32_MAX ? INT32_MAX : (int32_t)saf_stat_size;
680+
*size = saf_stat_size > INT64_MAX ? INT64_MAX : (int64_t)saf_stat_size;
681681

682682
(*env)->PopLocalFrame(env, NULL);
683683
return saf_stat_is_directory ? RETRO_VFS_STAT_IS_VALID | RETRO_VFS_STAT_IS_DIRECTORY : RETRO_VFS_STAT_IS_VALID;

libretro-common/vfs/vfs_implementation_smb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ int retro_vfs_closedir_smb(smb_dir_handle* dh)
544544
return 0;
545545
}
546546

547-
int retro_vfs_stat_smb(const char *path, int32_t *size)
547+
int retro_vfs_stat_smb(const char *path, int64_t *size)
548548
{
549549
char rel_path[PATH_MAX_LENGTH];
550550
struct smb2_stat_64 st;
@@ -572,7 +572,7 @@ int retro_vfs_stat_smb(const char *path, int32_t *size)
572572
return 0;
573573

574574
if (size)
575-
*size = (int32_t)st.smb2_size;
575+
*size = (int64_t)st.smb2_size;
576576

577577
return RETRO_VFS_STAT_IS_VALID |
578578
(st.smb2_type == SMB2_TYPE_DIRECTORY ? RETRO_VFS_STAT_IS_DIRECTORY : 0);

libretro-common/vfs/vfs_implementation_smb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct smbc_dirent* retro_vfs_readdir_smb(smb_dir_handle* dh);
6060
int retro_vfs_closedir_smb(smb_dir_handle* dh);
6161

6262
/* Stat */
63-
int retro_vfs_stat_smb(const char *path, int32_t *size);
63+
int retro_vfs_stat_smb(const char *path, int64_t *size);
6464

6565
/* Errors */
6666
int retro_vfs_file_error_smb(libretro_vfs_implementation_file *stream);

0 commit comments

Comments
 (0)