mirror of
https://github.com/libretro/libretro-prboom.git
synced 2024-11-27 02:00:49 +00:00
Update VFS-related parts of libretro-common
This commit is contained in:
parent
6ce9d90685
commit
dc45854223
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (file_path.c).
|
||||
@ -32,8 +32,6 @@
|
||||
#include <file/file_path.h>
|
||||
#include <retro_assert.h>
|
||||
#include <string/stdstring.h>
|
||||
#define VFS_FRONTEND
|
||||
#include <vfs/vfs_implementation.h>
|
||||
|
||||
/* TODO: There are probably some unnecessary things on this huge include list now but I'm too afraid to touch it */
|
||||
#ifdef __APPLE__
|
||||
@ -87,7 +85,7 @@
|
||||
#include <fileXio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
#include <cell/cell_fs.h>
|
||||
#endif
|
||||
|
||||
@ -114,137 +112,6 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
const struct retro_vfs_interface*
|
||||
vfs_iface = vfs_info->iface;
|
||||
|
||||
path_stat_cb = NULL;
|
||||
path_mkdir_cb = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#define path_stat_internal(path, size) ((path_stat_cb != NULL) ? path_stat_cb((path), (size)) : retro_vfs_stat_impl((path), (size)))
|
||||
|
||||
#define path_mkdir_norecurse(dir) ((path_mkdir_cb != NULL) ? path_mkdir_cb((dir)) : retro_vfs_mkdir_impl((dir)))
|
||||
|
||||
int path_stat(const char *path)
|
||||
{
|
||||
return path_stat_internal(path, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* path_is_directory:
|
||||
* @path : path
|
||||
*
|
||||
* Checks if path is a directory.
|
||||
*
|
||||
* Returns: true (1) if path is a directory, otherwise false (0).
|
||||
*/
|
||||
bool path_is_directory(const char *path)
|
||||
{
|
||||
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
|
||||
}
|
||||
|
||||
bool path_is_character_special(const char *path)
|
||||
{
|
||||
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
|
||||
}
|
||||
|
||||
bool path_is_valid(const char *path)
|
||||
{
|
||||
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
|
||||
}
|
||||
|
||||
int32_t path_get_size(const char *path)
|
||||
{
|
||||
int32_t filesize = 0;
|
||||
if (path_stat_internal(path, &filesize) != 0)
|
||||
return filesize;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* path_mkdir:
|
||||
* @dir : directory
|
||||
*
|
||||
* Create directory on filesystem.
|
||||
*
|
||||
* Returns: true (1) if directory could be created, otherwise false (0).
|
||||
**/
|
||||
bool path_mkdir(const char *dir)
|
||||
{
|
||||
bool sret = false;
|
||||
bool norecurse = false;
|
||||
char *basedir = NULL;
|
||||
|
||||
if (!(dir && *dir))
|
||||
return false;
|
||||
|
||||
/* Use heap. Real chance of stack
|
||||
* overflow if we recurse too hard. */
|
||||
basedir = strdup(dir);
|
||||
|
||||
if (!basedir)
|
||||
return false;
|
||||
|
||||
path_parent_dir(basedir);
|
||||
|
||||
if (!*basedir || !strcmp(basedir, dir))
|
||||
{
|
||||
free(basedir);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(GEKKO)
|
||||
{
|
||||
size_t len = strlen(basedir);
|
||||
|
||||
/* path_parent_dir() keeps the trailing slash.
|
||||
* On Wii, mkdir() fails if the path has a
|
||||
* trailing slash...
|
||||
* We must therefore remove it. */
|
||||
if (len > 0)
|
||||
if (basedir[len - 1] == '/')
|
||||
basedir[len - 1] = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
if (path_is_directory(basedir))
|
||||
norecurse = true;
|
||||
else
|
||||
{
|
||||
sret = path_mkdir(basedir);
|
||||
|
||||
if (sret)
|
||||
norecurse = true;
|
||||
}
|
||||
|
||||
free(basedir);
|
||||
|
||||
if (norecurse)
|
||||
{
|
||||
int ret = path_mkdir_norecurse(dir);
|
||||
|
||||
/* Don't treat this as an error. */
|
||||
if (ret == -2 && path_is_directory(dir))
|
||||
return true;
|
||||
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
return sret;
|
||||
}
|
||||
|
||||
/**
|
||||
* path_get_archive_delim:
|
||||
* @path : path
|
||||
@ -393,11 +260,11 @@ void fill_pathname(char *out_path, const char *in_path,
|
||||
* present in 'in_path', it will be ignored.
|
||||
*
|
||||
*/
|
||||
void fill_pathname_noext(char *out_path, const char *in_path,
|
||||
size_t fill_pathname_noext(char *out_path, const char *in_path,
|
||||
const char *replace, size_t size)
|
||||
{
|
||||
strlcpy(out_path, in_path, size);
|
||||
strlcat(out_path, replace, size);
|
||||
return strlcat(out_path, replace, size);
|
||||
}
|
||||
|
||||
char *find_last_slash(const char *str)
|
||||
@ -435,12 +302,8 @@ void fill_pathname_slash(char *path, size_t size)
|
||||
/* Try to preserve slash type. */
|
||||
if (last_slash != (path + path_len - 1))
|
||||
{
|
||||
char join_str[2];
|
||||
|
||||
join_str[0] = '\0';
|
||||
|
||||
strlcpy(join_str, last_slash, sizeof(join_str));
|
||||
strlcat(path, join_str, size);
|
||||
path[path_len] = last_slash[0];
|
||||
path[path_len+1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,7 +324,7 @@ void fill_pathname_slash(char *path, size_t size)
|
||||
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
||||
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
||||
**/
|
||||
void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
const char *replace, size_t size)
|
||||
{
|
||||
const char *base = NULL;
|
||||
@ -469,7 +332,7 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
fill_pathname_slash(in_dir, size);
|
||||
base = path_basename(in_basename);
|
||||
strlcat(in_dir, base, size);
|
||||
strlcat(in_dir, replace, size);
|
||||
return strlcat(in_dir, replace, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -480,14 +343,14 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
*
|
||||
* Copies basename of @in_path into @out_path.
|
||||
**/
|
||||
void fill_pathname_base(char *out, const char *in_path, size_t size)
|
||||
size_t fill_pathname_base(char *out, const char *in_path, size_t size)
|
||||
{
|
||||
const char *ptr = path_basename(in_path);
|
||||
|
||||
if (!ptr)
|
||||
ptr = in_path;
|
||||
|
||||
strlcpy(out, ptr, size);
|
||||
return strlcpy(out, ptr, size);
|
||||
}
|
||||
|
||||
void fill_pathname_base_noext(char *out,
|
||||
@ -497,12 +360,12 @@ void fill_pathname_base_noext(char *out,
|
||||
path_remove_extension(out);
|
||||
}
|
||||
|
||||
void fill_pathname_base_ext(char *out,
|
||||
size_t fill_pathname_base_ext(char *out,
|
||||
const char *in_path, const char *ext,
|
||||
size_t size)
|
||||
{
|
||||
fill_pathname_base_noext(out, in_path, size);
|
||||
strlcat(out, ext, size);
|
||||
return strlcat(out, ext, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -597,7 +460,7 @@ void fill_pathname_parent_dir(char *out_dir,
|
||||
* E.g.:
|
||||
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
|
||||
**/
|
||||
void fill_dated_filename(char *out_filename,
|
||||
size_t fill_dated_filename(char *out_filename,
|
||||
const char *ext, size_t size)
|
||||
{
|
||||
time_t cur_time = time(NULL);
|
||||
@ -605,7 +468,7 @@ void fill_dated_filename(char *out_filename,
|
||||
|
||||
strftime(out_filename, size,
|
||||
"RetroArch-%m%d-%H%M%S", tm_);
|
||||
strlcat(out_filename, ext, size);
|
||||
return strlcat(out_filename, ext, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -629,11 +492,20 @@ void fill_str_dated_filename(char *out_filename,
|
||||
const struct tm* tm_ = localtime(&cur_time);
|
||||
|
||||
format[0] = '\0';
|
||||
strftime(format, sizeof(format), "-%y%m%d-%H%M%S.", tm_);
|
||||
|
||||
fill_pathname_join_concat_noext(out_filename,
|
||||
in_str, format, ext,
|
||||
size);
|
||||
if (string_is_empty(ext))
|
||||
{
|
||||
strftime(format, sizeof(format), "-%y%m%d-%H%M%S", tm_);
|
||||
fill_pathname_noext(out_filename, in_str, format, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
strftime(format, sizeof(format), "-%y%m%d-%H%M%S.", tm_);
|
||||
|
||||
fill_pathname_join_concat_noext(out_filename,
|
||||
in_str, format, ext,
|
||||
size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -646,6 +518,7 @@ void fill_str_dated_filename(char *out_filename,
|
||||
void path_basedir(char *path)
|
||||
{
|
||||
char *last = NULL;
|
||||
|
||||
if (strlen(path) < 2)
|
||||
return;
|
||||
|
||||
@ -747,35 +620,131 @@ bool path_is_absolute(const char *path)
|
||||
|
||||
/**
|
||||
* path_resolve_realpath:
|
||||
* @buf : buffer for path
|
||||
* @buf : input and output buffer for path
|
||||
* @size : size of buffer
|
||||
* @resolve_symlinks : whether to resolve symlinks or not
|
||||
*
|
||||
* Turns relative paths into absolute paths and
|
||||
* resolves use of "." and ".." in absolute paths.
|
||||
* If relative, rebases on current working dir.
|
||||
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
|
||||
*
|
||||
* Relative paths are rebased on the current working dir.
|
||||
*
|
||||
* Returns: @buf if successful, NULL otherwise.
|
||||
* Note: Not implemented on consoles
|
||||
* Note: Symlinks are only resolved on Unix-likes
|
||||
* Note: The current working dir might not be what you expect,
|
||||
* e.g. on Android it is "/"
|
||||
* Use of fill_pathname_resolve_relative() should be prefered
|
||||
**/
|
||||
void path_resolve_realpath(char *buf, size_t size)
|
||||
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks)
|
||||
{
|
||||
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
||||
char tmp[PATH_MAX_LENGTH];
|
||||
|
||||
tmp[0] = '\0';
|
||||
|
||||
strlcpy(tmp, buf, sizeof(tmp));
|
||||
|
||||
#ifdef _WIN32
|
||||
strlcpy(tmp, buf, sizeof(tmp));
|
||||
if (!_fullpath(buf, tmp, size))
|
||||
{
|
||||
strlcpy(buf, tmp, size);
|
||||
return NULL;
|
||||
}
|
||||
return buf;
|
||||
#else
|
||||
size_t t;
|
||||
char *p;
|
||||
const char *next;
|
||||
const char *buf_end;
|
||||
|
||||
/* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf.
|
||||
* Technically, PATH_MAX_LENGTH needn't be defined, but we rely on it anyways.
|
||||
* POSIX 2008 can automatically allocate for you,
|
||||
* but don't rely on that. */
|
||||
if (!realpath(tmp, buf))
|
||||
strlcpy(buf, tmp, size);
|
||||
if (resolve_symlinks)
|
||||
{
|
||||
strlcpy(tmp, buf, sizeof(tmp));
|
||||
|
||||
/* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf.
|
||||
* Technically, PATH_MAX_LENGTH needn't be defined, but we rely on it anyways.
|
||||
* POSIX 2008 can automatically allocate for you,
|
||||
* but don't rely on that. */
|
||||
if (!realpath(tmp, buf))
|
||||
{
|
||||
strlcpy(buf, tmp, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
t = 0; /* length of output */
|
||||
buf_end = buf + strlen(buf);
|
||||
|
||||
if (!path_is_absolute(buf))
|
||||
{
|
||||
size_t len;
|
||||
/* rebase on working directory */
|
||||
if (!getcwd(tmp, PATH_MAX_LENGTH-1))
|
||||
return NULL;
|
||||
|
||||
len = strlen(tmp);
|
||||
t += len;
|
||||
|
||||
if (tmp[len-1] != '/')
|
||||
tmp[t++] = '/';
|
||||
|
||||
if (string_is_empty(buf))
|
||||
goto end;
|
||||
|
||||
p = buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* UNIX paths can start with multiple '/', copy those */
|
||||
for (p = buf; *p == '/'; p++)
|
||||
tmp[t++] = '/';
|
||||
}
|
||||
|
||||
/* p points to just after a slash while 'next' points to the next slash
|
||||
* if there are no slashes, they point relative to where one would be */
|
||||
do
|
||||
{
|
||||
next = strchr(p, '/');
|
||||
if (!next)
|
||||
next = buf_end;
|
||||
|
||||
if ((next - p == 2 && p[0] == '.' && p[1] == '.'))
|
||||
{
|
||||
p += 3;
|
||||
|
||||
/* fail for illegal /.., //.. etc */
|
||||
if (t == 1 || tmp[t-2] == '/')
|
||||
return NULL;
|
||||
|
||||
/* delete previous segment in tmp by adjusting size t
|
||||
* tmp[t-1] == '/', find '/' before that */
|
||||
t = t-2;
|
||||
while (tmp[t] != '/')
|
||||
t--;
|
||||
t++;
|
||||
}
|
||||
else if (next - p == 1 && p[0] == '.')
|
||||
p += 2;
|
||||
else if (next - p == 0)
|
||||
p += 1;
|
||||
else
|
||||
{
|
||||
/* fail when truncating */
|
||||
if (t + next-p+1 > PATH_MAX_LENGTH-1)
|
||||
return NULL;
|
||||
|
||||
while (p <= next)
|
||||
tmp[t++] = *p++;
|
||||
}
|
||||
|
||||
}
|
||||
while (next < buf_end);
|
||||
|
||||
end:
|
||||
tmp[t] = '\0';
|
||||
strlcpy(buf, tmp, size);
|
||||
return buf;
|
||||
#endif
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -792,10 +761,10 @@ void path_resolve_realpath(char *buf, size_t size)
|
||||
*
|
||||
* E.g. path /a/b/e/f.cg with base /a/b/c/d/ turns into ../../e/f.cg
|
||||
**/
|
||||
void path_relative_to(char *out,
|
||||
size_t path_relative_to(char *out,
|
||||
const char *path, const char *base, size_t size)
|
||||
{
|
||||
unsigned i;
|
||||
size_t i;
|
||||
const char *trimmed_path, *trimmed_base;
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -803,10 +772,7 @@ void path_relative_to(char *out,
|
||||
if (strlen(path) >= 2 && strlen(base) >= 2
|
||||
&& path[1] == ':' && base[1] == ':'
|
||||
&& path[0] != base[0])
|
||||
{
|
||||
out[0] = '\0';
|
||||
strlcat(out, path, size);
|
||||
}
|
||||
return strlcpy(out, path, size);
|
||||
#endif
|
||||
|
||||
/* Trim common beginning */
|
||||
@ -818,9 +784,10 @@ void path_relative_to(char *out,
|
||||
/* Each segment of base turns into ".." */
|
||||
out[0] = '\0';
|
||||
for (i = 0; trimmed_base[i]; i++)
|
||||
if (trimmed_base[i] == '/' || trimmed_base[i] == '\\')
|
||||
strlcat(out, "../", size); /* Use '/' as universal separator */
|
||||
strlcat(out, trimmed_path, size);
|
||||
if (trimmed_base[i] == path_default_slash_c())
|
||||
strlcat(out, ".." path_default_slash(), size);
|
||||
|
||||
return strlcat(out, trimmed_path, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -846,7 +813,7 @@ void fill_pathname_resolve_relative(char *out_path,
|
||||
|
||||
fill_pathname_basedir(out_path, in_refpath, size);
|
||||
strlcat(out_path, in_path, size);
|
||||
path_resolve_realpath(out_path, size);
|
||||
path_resolve_realpath(out_path, size, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -860,7 +827,7 @@ void fill_pathname_resolve_relative(char *out_path,
|
||||
* Makes sure not to get two consecutive slashes
|
||||
* between directory and path.
|
||||
**/
|
||||
void fill_pathname_join(char *out_path,
|
||||
size_t fill_pathname_join(char *out_path,
|
||||
const char *dir, const char *path, size_t size)
|
||||
{
|
||||
if (out_path != dir)
|
||||
@ -869,10 +836,10 @@ void fill_pathname_join(char *out_path,
|
||||
if (*out_path)
|
||||
fill_pathname_slash(out_path, size);
|
||||
|
||||
strlcat(out_path, path, size);
|
||||
return strlcat(out_path, path, size);
|
||||
}
|
||||
|
||||
void fill_pathname_join_special_ext(char *out_path,
|
||||
size_t fill_pathname_join_special_ext(char *out_path,
|
||||
const char *dir, const char *path,
|
||||
const char *last, const char *ext,
|
||||
size_t size)
|
||||
@ -882,26 +849,25 @@ void fill_pathname_join_special_ext(char *out_path,
|
||||
fill_pathname_slash(out_path, size);
|
||||
|
||||
strlcat(out_path, last, size);
|
||||
strlcat(out_path, ext, size);
|
||||
return strlcat(out_path, ext, size);
|
||||
}
|
||||
|
||||
void fill_pathname_join_concat_noext(
|
||||
char *out_path,
|
||||
size_t fill_pathname_join_concat_noext(char *out_path,
|
||||
const char *dir, const char *path,
|
||||
const char *concat,
|
||||
size_t size)
|
||||
{
|
||||
fill_pathname_noext(out_path, dir, path, size);
|
||||
strlcat(out_path, concat, size);
|
||||
return strlcat(out_path, concat, size);
|
||||
}
|
||||
|
||||
void fill_pathname_join_concat(char *out_path,
|
||||
size_t fill_pathname_join_concat(char *out_path,
|
||||
const char *dir, const char *path,
|
||||
const char *concat,
|
||||
size_t size)
|
||||
{
|
||||
fill_pathname_join(out_path, dir, path, size);
|
||||
strlcat(out_path, concat, size);
|
||||
return strlcat(out_path, concat, size);
|
||||
}
|
||||
|
||||
void fill_pathname_join_noext(char *out_path,
|
||||
@ -922,7 +888,7 @@ void fill_pathname_join_noext(char *out_path,
|
||||
* Joins a directory (@dir) and path (@path) together
|
||||
* using the given delimiter (@delim).
|
||||
**/
|
||||
void fill_pathname_join_delim(char *out_path, const char *dir,
|
||||
size_t fill_pathname_join_delim(char *out_path, const char *dir,
|
||||
const char *path, const char delim, size_t size)
|
||||
{
|
||||
size_t copied;
|
||||
@ -936,15 +902,16 @@ void fill_pathname_join_delim(char *out_path, const char *dir,
|
||||
out_path[copied+1] = '\0';
|
||||
|
||||
if (path)
|
||||
strlcat(out_path, path, size);
|
||||
copied = strlcat(out_path, path, size);
|
||||
return copied;
|
||||
}
|
||||
|
||||
void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||
size_t fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||
const char *path, const char delim, const char *concat,
|
||||
size_t size)
|
||||
{
|
||||
fill_pathname_join_delim(out_path, dir, path, delim, size);
|
||||
strlcat(out_path, concat, size);
|
||||
return strlcat(out_path, concat, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -962,7 +929,7 @@ void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||
* E.g.: "/path/to/game.img" -> game.img
|
||||
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
|
||||
*/
|
||||
void fill_short_pathname_representation(char* out_rep,
|
||||
size_t fill_short_pathname_representation(char* out_rep,
|
||||
const char *in_path, size_t size)
|
||||
{
|
||||
char path_short[PATH_MAX_LENGTH];
|
||||
@ -972,7 +939,7 @@ void fill_short_pathname_representation(char* out_rep,
|
||||
fill_pathname(path_short, path_basename(in_path), "",
|
||||
sizeof(path_short));
|
||||
|
||||
strlcpy(out_rep, path_short, size);
|
||||
return strlcpy(out_rep, path_short, size);
|
||||
}
|
||||
|
||||
void fill_short_pathname_representation_noext(char* out_rep,
|
||||
@ -1189,10 +1156,27 @@ void fill_pathname_application_path(char *s, size_t len)
|
||||
CFURLRef bundle_url = CFBundleCopyBundleURL(bundle);
|
||||
CFStringRef bundle_path = CFURLCopyPath(bundle_url);
|
||||
CFStringGetCString(bundle_path, s, len, kCFStringEncodingUTF8);
|
||||
#ifdef HAVE_COCOATOUCH
|
||||
{
|
||||
/* This needs to be done so that the path becomes
|
||||
* /private/var/... and this
|
||||
* is used consistently throughout for the iOS bundle path */
|
||||
char resolved_bundle_dir_buf[PATH_MAX_LENGTH] = {0};
|
||||
if (realpath(s, resolved_bundle_dir_buf))
|
||||
{
|
||||
strlcpy(s, resolved_bundle_dir_buf, len - 1);
|
||||
strlcat(s, "/", len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CFRelease(bundle_path);
|
||||
CFRelease(bundle_url);
|
||||
|
||||
#ifndef HAVE_COCOATOUCH
|
||||
/* Not sure what this does but it breaks
|
||||
* stuff for iOS, so skipping */
|
||||
retro_assert(strlcat(s, "nobin", len) < len);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#elif defined(__HAIKU__)
|
||||
@ -1265,8 +1249,8 @@ void fill_pathname_home_dir(char *s, size_t len)
|
||||
|
||||
bool is_path_accessible_using_standard_io(const char *path)
|
||||
{
|
||||
bool result = true;
|
||||
#ifdef __WINRT__
|
||||
bool result;
|
||||
size_t path_sizeof = PATH_MAX_LENGTH * sizeof(char);
|
||||
char *relative_path_abbrev = (char*)malloc(path_sizeof);
|
||||
fill_pathname_abbreviate_special(relative_path_abbrev, path, path_sizeof);
|
||||
@ -1274,8 +1258,6 @@ bool is_path_accessible_using_standard_io(const char *path)
|
||||
result = strlen(relative_path_abbrev) >= 2 && (relative_path_abbrev[0] == ':' || relative_path_abbrev[0] == '~') && path_char_is_slash(relative_path_abbrev[1]);
|
||||
|
||||
free(relative_path_abbrev);
|
||||
return result;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (file_path.h).
|
||||
@ -147,14 +147,22 @@ void path_parent_dir(char *path);
|
||||
|
||||
/**
|
||||
* path_resolve_realpath:
|
||||
* @buf : buffer for path
|
||||
* @buf : input and output buffer for path
|
||||
* @size : size of buffer
|
||||
* @resolve_symlinks : whether to resolve symlinks or not
|
||||
*
|
||||
* Turns relative paths into absolute paths and
|
||||
* resolves use of "." and ".." in absolute paths.
|
||||
* If relative, rebases on current working dir.
|
||||
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
|
||||
*
|
||||
* Relative paths are rebased on the current working dir.
|
||||
*
|
||||
* Returns: @buf if successful, NULL otherwise.
|
||||
* Note: Not implemented on consoles
|
||||
* Note: Symlinks are only resolved on Unix-likes
|
||||
* Note: The current working dir might not be what you expect,
|
||||
* e.g. on Android it is "/"
|
||||
* Use of fill_pathname_resolve_relative() should be prefered
|
||||
**/
|
||||
void path_resolve_realpath(char *buf, size_t size);
|
||||
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
|
||||
|
||||
/**
|
||||
* path_relative_to:
|
||||
@ -170,7 +178,7 @@ void path_resolve_realpath(char *buf, size_t size);
|
||||
*
|
||||
* E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp
|
||||
**/
|
||||
void path_relative_to(char *out, const char *path, const char *base, size_t size);
|
||||
size_t path_relative_to(char *out, const char *path, const char *base, size_t size);
|
||||
|
||||
/**
|
||||
* path_is_absolute:
|
||||
@ -218,7 +226,7 @@ void fill_pathname(char *out_path, const char *in_path,
|
||||
* E.g.:
|
||||
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
|
||||
**/
|
||||
void fill_dated_filename(char *out_filename,
|
||||
size_t fill_dated_filename(char *out_filename,
|
||||
const char *ext, size_t size);
|
||||
|
||||
/**
|
||||
@ -251,7 +259,7 @@ void fill_str_dated_filename(char *out_filename,
|
||||
* present in 'in_path', it will be ignored.
|
||||
*
|
||||
*/
|
||||
void fill_pathname_noext(char *out_path, const char *in_path,
|
||||
size_t fill_pathname_noext(char *out_path, const char *in_path,
|
||||
const char *replace, size_t size);
|
||||
|
||||
/**
|
||||
@ -281,7 +289,7 @@ char *find_last_slash(const char *str);
|
||||
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
||||
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
||||
**/
|
||||
void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
const char *replace, size_t size);
|
||||
|
||||
/**
|
||||
@ -292,12 +300,12 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
*
|
||||
* Copies basename of @in_path into @out_path.
|
||||
**/
|
||||
void fill_pathname_base(char *out_path, const char *in_path, size_t size);
|
||||
size_t fill_pathname_base(char *out_path, const char *in_path, size_t size);
|
||||
|
||||
void fill_pathname_base_noext(char *out_dir,
|
||||
const char *in_path, size_t size);
|
||||
|
||||
void fill_pathname_base_ext(char *out,
|
||||
size_t fill_pathname_base_ext(char *out,
|
||||
const char *in_path, const char *ext,
|
||||
size_t size);
|
||||
|
||||
@ -368,21 +376,20 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
|
||||
* Makes sure not to get two consecutive slashes
|
||||
* between directory and path.
|
||||
**/
|
||||
void fill_pathname_join(char *out_path, const char *dir,
|
||||
size_t fill_pathname_join(char *out_path, const char *dir,
|
||||
const char *path, size_t size);
|
||||
|
||||
void fill_pathname_join_special_ext(char *out_path,
|
||||
size_t fill_pathname_join_special_ext(char *out_path,
|
||||
const char *dir, const char *path,
|
||||
const char *last, const char *ext,
|
||||
size_t size);
|
||||
|
||||
void fill_pathname_join_concat_noext(
|
||||
char *out_path,
|
||||
size_t fill_pathname_join_concat_noext(char *out_path,
|
||||
const char *dir, const char *path,
|
||||
const char *concat,
|
||||
size_t size);
|
||||
|
||||
void fill_pathname_join_concat(char *out_path,
|
||||
size_t fill_pathname_join_concat(char *out_path,
|
||||
const char *dir, const char *path,
|
||||
const char *concat,
|
||||
size_t size);
|
||||
@ -401,10 +408,10 @@ void fill_pathname_join_noext(char *out_path,
|
||||
* Joins a directory (@dir) and path (@path) together
|
||||
* using the given delimiter (@delim).
|
||||
**/
|
||||
void fill_pathname_join_delim(char *out_path, const char *dir,
|
||||
size_t fill_pathname_join_delim(char *out_path, const char *dir,
|
||||
const char *path, const char delim, size_t size);
|
||||
|
||||
void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||
size_t fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||
const char *path, const char delim, const char *concat,
|
||||
size_t size);
|
||||
|
||||
@ -423,7 +430,7 @@ void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||
* E.g.: "/path/to/game.img" -> game.img
|
||||
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
|
||||
*/
|
||||
void fill_short_pathname_representation(char* out_rep,
|
||||
size_t fill_short_pathname_representation(char* out_rep,
|
||||
const char *in_path, size_t size);
|
||||
|
||||
void fill_short_pathname_representation_noext(char* out_rep,
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include <Xtl.h>
|
||||
#endif
|
||||
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
#include <sys/fs_external.h>
|
||||
#endif
|
||||
|
||||
@ -75,7 +75,7 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
|
||||
}
|
||||
|
||||
#ifndef PATH_MAX_LENGTH
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
|
||||
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU)
|
||||
#define PATH_MAX_LENGTH 512
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (vfs_implementation.h).
|
||||
@ -23,30 +23,13 @@
|
||||
#ifndef __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
||||
#define __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <libretro.h>
|
||||
#include <retro_environment.h>
|
||||
#include <vfs/vfs.h>
|
||||
|
||||
/* Replace the following symbol with something appropriate
|
||||
* to signify the file is being compiled for a front end instead of a core.
|
||||
* This allows the same code to act as reference implementation
|
||||
* for VFS and as fallbacks for when the front end does not provide VFS functionality.
|
||||
*/
|
||||
|
||||
#ifdef VFS_FRONTEND
|
||||
typedef struct retro_vfs_file_handle libretro_vfs_implementation_file;
|
||||
#else
|
||||
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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints);
|
||||
|
||||
@ -88,8 +71,6 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *dirstream);
|
||||
|
||||
int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *dirstream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (vfs_implementation.c).
|
||||
@ -41,11 +41,12 @@
|
||||
# include <xtl.h>
|
||||
# define INVALID_FILE_ATTRIBUTES -1
|
||||
# else
|
||||
# include <io.h>
|
||||
|
||||
# include <fcntl.h>
|
||||
# include <direct.h>
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# include <io.h>
|
||||
#else
|
||||
# if defined(PSP)
|
||||
# include <pspiofilemgr.h>
|
||||
@ -67,7 +68,7 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __CELLOS_LV2__
|
||||
#if defined (__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
#include <cell/cell_fs.h>
|
||||
#define O_RDONLY CELL_FS_O_RDONLY
|
||||
#define O_WRONLY CELL_FS_O_WRONLY
|
||||
@ -150,7 +151,7 @@
|
||||
#include <fileXio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
#include <cell/cell_fs.h>
|
||||
#endif
|
||||
|
||||
@ -171,18 +172,12 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
#if defined(_WIN32)
|
||||
#if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
#define ATLEAST_VC2005
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#ifndef VFS_FRONTEND
|
||||
#define VFS_FRONTEND
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <vfs/vfs_implementation.h>
|
||||
#include <libretro.h>
|
||||
#include <memmap.h>
|
||||
@ -190,26 +185,11 @@
|
||||
#include <compat/fopen_utf8.h>
|
||||
#include <file/file_path.h>
|
||||
|
||||
#define RFILE_HINT_UNBUFFERED (1 << 8)
|
||||
#ifdef HAVE_CDROM
|
||||
#include <vfs/vfs_implementation_cdrom.h>
|
||||
#endif
|
||||
|
||||
#ifdef VFS_FRONTEND
|
||||
struct retro_vfs_file_handle
|
||||
#else
|
||||
struct libretro_vfs_implementation_file
|
||||
#endif
|
||||
{
|
||||
int fd;
|
||||
unsigned hints;
|
||||
int64_t size;
|
||||
char *buf;
|
||||
FILE *fp;
|
||||
char* orig_path;
|
||||
#if defined(HAVE_MMAP)
|
||||
uint64_t mappos;
|
||||
uint64_t mapsize;
|
||||
uint8_t *mapped;
|
||||
#endif
|
||||
};
|
||||
#define RFILE_HINT_UNBUFFERED (1 << 8)
|
||||
|
||||
int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, int64_t offset, int whence)
|
||||
{
|
||||
@ -218,22 +198,30 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
|
||||
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
{
|
||||
#ifdef HAVE_CDROM
|
||||
if (stream->scheme == VFS_SCHEME_CDROM)
|
||||
return retro_vfs_file_seek_cdrom(stream, offset, whence);
|
||||
#endif
|
||||
/* VC2005 and up have a special 64-bit fseek */
|
||||
#ifdef ATLEAST_VC2005
|
||||
return _fseeki64(stream->fp, offset, whence);
|
||||
#elif defined(__CELLOS_LV2__) || defined(_MSC_VER) && _MSC_VER <= 1310
|
||||
return fseek(stream->fp, (long)offset, whence);
|
||||
#elif defined(PS2)
|
||||
int64_t ret = fileXioLseek(fileno(stream->fp), (off_t)offset, whence);
|
||||
/* fileXioLseek could return positive numbers */
|
||||
if (ret > 0)
|
||||
return 0;
|
||||
return ret;
|
||||
{
|
||||
int64_t ret = fileXioLseek(fileno(stream->fp), (off_t)offset, whence);
|
||||
/* fileXioLseek could return positive numbers */
|
||||
if (ret > 0)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
#elif defined(ORBIS)
|
||||
int ret = orbisLseek(stream->fd, offset, whence);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
{
|
||||
int ret = orbisLseek(stream->fd, offset, whence);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return fseeko(stream->fp, (off_t)offset, whence);
|
||||
#endif
|
||||
@ -298,12 +286,14 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
||||
const char *mode_str = NULL;
|
||||
libretro_vfs_implementation_file *stream = (libretro_vfs_implementation_file*)
|
||||
calloc(1, sizeof(*stream));
|
||||
#if defined(VFS_FRONTEND) || defined(HAVE_CDROM)
|
||||
int path_len = (int)strlen(path);
|
||||
#endif
|
||||
|
||||
#ifdef VFS_FRONTEND
|
||||
const char *dumb_prefix = "vfsonly://";
|
||||
size_t dumb_prefix_siz = strlen(dumb_prefix);
|
||||
int dumb_prefix_len = (int)dumb_prefix_siz;
|
||||
int path_len = (int)strlen(path);
|
||||
|
||||
if (path_len >= dumb_prefix_len)
|
||||
{
|
||||
@ -312,6 +302,23 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CDROM
|
||||
{
|
||||
const char *cdrom_prefix = "cdrom://";
|
||||
size_t cdrom_prefix_siz = strlen(cdrom_prefix);
|
||||
int cdrom_prefix_len = (int)cdrom_prefix_siz;
|
||||
|
||||
if (path_len > cdrom_prefix_len)
|
||||
{
|
||||
if (!memcmp(path, cdrom_prefix, cdrom_prefix_len))
|
||||
{
|
||||
path += cdrom_prefix_siz;
|
||||
stream->scheme = VFS_SCHEME_CDROM;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!stream)
|
||||
return NULL;
|
||||
|
||||
@ -398,11 +405,29 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
||||
}
|
||||
stream->fd = fd;
|
||||
#else
|
||||
FILE *fp = (FILE*)fopen_utf8(path, mode_str);
|
||||
FILE *fp;
|
||||
#ifdef HAVE_CDROM
|
||||
if (stream->scheme == VFS_SCHEME_CDROM)
|
||||
{
|
||||
retro_vfs_file_open_cdrom(stream, path, mode, hints);
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
if (!stream->fh)
|
||||
goto error;
|
||||
#else
|
||||
if (!stream->fp)
|
||||
goto error;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
fp = (FILE*)fopen_utf8(path, mode_str);
|
||||
|
||||
if (!fp)
|
||||
goto error;
|
||||
if (!fp)
|
||||
goto error;
|
||||
|
||||
stream->fp = fp;
|
||||
}
|
||||
/* Regarding setvbuf:
|
||||
*
|
||||
* https://www.freebsd.org/cgi/man.cgi?query=setvbuf&apropos=0&sektion=0&manpath=FreeBSD+11.1-RELEASE&arch=default&format=html
|
||||
@ -413,10 +438,13 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
||||
* Since C89 does not support specifying a null buffer with a non-zero size, we create and track our own buffer for it.
|
||||
*/
|
||||
/* TODO: this is only useful for a few platforms, find which and add ifdef */
|
||||
stream->fp = fp;
|
||||
#if !defined(PS2) && !defined(PSP)
|
||||
stream->buf = (char*)calloc(1, 0x4000);
|
||||
setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000);
|
||||
if (stream->scheme != VFS_SCHEME_CDROM)
|
||||
{
|
||||
stream->buf = (char*)calloc(1, 0x4000);
|
||||
if (stream->fp)
|
||||
setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@ -465,12 +493,26 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
||||
stream->size = orbisLseek(stream->fd, 0, SEEK_END);
|
||||
orbisLseek(stream->fd, 0, SEEK_SET);
|
||||
#else
|
||||
retro_vfs_file_seek_internal(stream, 0, SEEK_SET);
|
||||
retro_vfs_file_seek_internal(stream, 0, SEEK_END);
|
||||
#ifdef HAVE_CDROM
|
||||
if (stream->scheme == VFS_SCHEME_CDROM)
|
||||
{
|
||||
retro_vfs_file_seek_cdrom(stream, 0, SEEK_SET);
|
||||
retro_vfs_file_seek_cdrom(stream, 0, SEEK_END);
|
||||
|
||||
stream->size = retro_vfs_file_tell_impl(stream);
|
||||
stream->size = retro_vfs_file_tell_impl(stream);
|
||||
|
||||
retro_vfs_file_seek_internal(stream, 0, SEEK_SET);
|
||||
retro_vfs_file_seek_cdrom(stream, 0, SEEK_SET);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
retro_vfs_file_seek_internal(stream, 0, SEEK_SET);
|
||||
retro_vfs_file_seek_internal(stream, 0, SEEK_END);
|
||||
|
||||
stream->size = retro_vfs_file_tell_impl(stream);
|
||||
|
||||
retro_vfs_file_seek_internal(stream, 0, SEEK_SET);
|
||||
}
|
||||
#endif
|
||||
return stream;
|
||||
|
||||
@ -484,10 +526,20 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream)
|
||||
if (!stream)
|
||||
return -1;
|
||||
|
||||
#ifdef HAVE_CDROM
|
||||
if (stream->scheme == VFS_SCHEME_CDROM)
|
||||
{
|
||||
retro_vfs_file_close_cdrom(stream);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
{
|
||||
if (stream->fp)
|
||||
{
|
||||
fclose(stream->fp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -506,10 +558,17 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream)
|
||||
close(stream->fd);
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_CDROM
|
||||
end:
|
||||
if (stream->cdrom.cue_buf)
|
||||
free(stream->cdrom.cue_buf);
|
||||
#endif
|
||||
if (stream->buf)
|
||||
free(stream->buf);
|
||||
|
||||
if (stream->orig_path)
|
||||
free(stream->orig_path);
|
||||
|
||||
free(stream);
|
||||
|
||||
return 0;
|
||||
@ -517,6 +576,10 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream)
|
||||
|
||||
int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream)
|
||||
{
|
||||
#ifdef HAVE_CDROM
|
||||
if (stream->scheme == VFS_SCHEME_CDROM)
|
||||
return retro_vfs_file_error_cdrom(stream);
|
||||
#endif
|
||||
#ifdef ORBIS
|
||||
/* TODO/FIXME - implement this? */
|
||||
return 0;
|
||||
@ -555,13 +618,19 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
|
||||
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
{
|
||||
#ifdef HAVE_CDROM
|
||||
if (stream->scheme == VFS_SCHEME_CDROM)
|
||||
return retro_vfs_file_tell_cdrom(stream);
|
||||
#endif
|
||||
#ifdef ORBIS
|
||||
int64_t ret = orbisLseek(stream->fd, 0, SEEK_CUR);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return ret;
|
||||
{
|
||||
int64_t ret = orbisLseek(stream->fd, 0, SEEK_CUR);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
/* VC2005 and up have a special 64-bit ftell */
|
||||
/* VC2005 and up have a special 64-bit ftell */
|
||||
#ifdef ATLEAST_VC2005
|
||||
return _ftelli64(stream->fp);
|
||||
#else
|
||||
@ -609,6 +678,10 @@ int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream,
|
||||
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
{
|
||||
#ifdef HAVE_CDROM
|
||||
if (stream->scheme == VFS_SCHEME_CDROM)
|
||||
return retro_vfs_file_read_cdrom(stream, s, len);
|
||||
#endif
|
||||
#ifdef ORBIS
|
||||
if (orbisRead(stream->fd, s, (size_t)len) < 0)
|
||||
return -1;
|
||||
@ -867,14 +940,16 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
|
||||
/* if fileXioGetStat fails */
|
||||
int dir_ret = fileXioDopen(path);
|
||||
is_dir = dir_ret > 0;
|
||||
fileXioDclose(dir_ret);
|
||||
if (is_dir) {
|
||||
fileXioDclose(dir_ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
is_dir = FIO_S_ISDIR(buf.mode);
|
||||
|
||||
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
|
||||
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
/* CellOS Lv2 */
|
||||
bool is_dir;
|
||||
bool is_character_special = false;
|
||||
@ -1020,7 +1095,7 @@ struct libretro_vfs_implementation_dir
|
||||
#elif defined(PS2)
|
||||
int directory;
|
||||
iox_dirent_t entry;
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
CellFsErrno error;
|
||||
int directory;
|
||||
CellFsDirent entry;
|
||||
@ -1039,18 +1114,20 @@ static bool dirent_check_error(libretro_vfs_implementation_dir *rdir)
|
||||
return (rdir->directory == INVALID_HANDLE_VALUE);
|
||||
#elif defined(VITA) || defined(PSP) || defined(PS2) || defined(ORBIS)
|
||||
return (rdir->directory < 0);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
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)
|
||||
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(
|
||||
const char *name, bool include_hidden)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
unsigned path_len;
|
||||
char path_buf[1024];
|
||||
size_t copied = 0;
|
||||
#if defined(LEGACY_WIN32)
|
||||
char *path_local = NULL;
|
||||
#else
|
||||
@ -1074,21 +1151,24 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i
|
||||
path_buf[0] = '\0';
|
||||
path_len = strlen(name);
|
||||
|
||||
copied = strlcpy(path_buf, name, sizeof(path_buf));
|
||||
|
||||
/* 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 (name[path_len - 1] != '\\')
|
||||
path_buf[copied++] = '\\';
|
||||
|
||||
path_buf[copied] = '*';
|
||||
path_buf[copied+1] = '\0';
|
||||
|
||||
#if defined(LEGACY_WIN32)
|
||||
path_local = utf8_to_local_string_alloc(path_buf);
|
||||
rdir->directory = FindFirstFile(path_local, &rdir->entry);
|
||||
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);
|
||||
path_wide = utf8_to_utf16_string_alloc(path_buf);
|
||||
rdir->directory = FindFirstFileW(path_wide, &rdir->entry);
|
||||
|
||||
if (path_wide)
|
||||
free(path_wide);
|
||||
@ -1101,7 +1181,7 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i
|
||||
#elif defined(_3DS)
|
||||
rdir->directory = !string_is_empty(name) ? opendir(name) : NULL;
|
||||
rdir->entry = NULL;
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
rdir->error = cellFsOpendir(name, &rdir->directory);
|
||||
#elif defined(ORBIS)
|
||||
rdir->directory = orbisDopen(name);
|
||||
@ -1143,7 +1223,7 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *rdir)
|
||||
int ret = ps2fileXioDread(rdir->directory, &record);
|
||||
rdir->entry = record;
|
||||
return ( ret > 0);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
uint64_t nread;
|
||||
rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread);
|
||||
return (nread != 0);
|
||||
@ -1158,27 +1238,32 @@ 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));
|
||||
{
|
||||
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);
|
||||
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));
|
||||
{
|
||||
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);
|
||||
if (name)
|
||||
free(name);
|
||||
}
|
||||
#endif
|
||||
return (char*)rdir->entry.cFileName;
|
||||
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(ORBIS)
|
||||
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) || defined(ORBIS)
|
||||
return rdir->entry.d_name;
|
||||
#elif defined(PS2)
|
||||
return rdir->entry.name;
|
||||
#else
|
||||
|
||||
if (!rdir || !rdir->entry)
|
||||
return NULL;
|
||||
return rdir->entry->d_name;
|
||||
#endif
|
||||
}
|
||||
@ -1198,7 +1283,7 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir)
|
||||
#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__)
|
||||
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
CellFsDirent *entry = (CellFsDirent*)&rdir->entry;
|
||||
return (entry->d_type == CELL_FS_TYPE_DIRECTORY);
|
||||
#elif defined(ORBIS)
|
||||
@ -1239,7 +1324,7 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir)
|
||||
sceIoDclose(rdir->directory);
|
||||
#elif defined(PS2)
|
||||
ps2fileXioDclose(rdir->directory);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
rdir->error = cellFsClosedir(rdir->directory);
|
||||
#elif defined(ORBIS)
|
||||
orbisDclose(rdir->directory);
|
||||
|
Loading…
Reference in New Issue
Block a user