mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-06 02:33:44 -04:00
android: Fully use raw FS access on vanilla builds
This commit is contained in:
parent
0c624f16a7
commit
e87635095a
1 changed files with 261 additions and 168 deletions
|
|
@ -145,6 +145,23 @@ static void StripTailDirSlashes(std::string& fname) {
|
||||||
fname.resize(i);
|
fname.resize(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
|
namespace {
|
||||||
|
std::string AndroidTranslateFilename(const std::string& file) {
|
||||||
|
std::optional<std::string> userDirLocation = AndroidStorage::GetUserDirectory();
|
||||||
|
if (userDirLocation) {
|
||||||
|
return *userDirLocation + file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidCanUseRawFS() {
|
||||||
|
return AndroidStorage::GetBuildFlavor() != AndroidStorage::AndroidBuildFlavors::GOOGLEPLAY;
|
||||||
|
}
|
||||||
|
} // anonymous namespace
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Exists(const std::string& filename) {
|
bool Exists(const std::string& filename) {
|
||||||
std::string copy(filename);
|
std::string copy(filename);
|
||||||
StripTailDirSlashes(copy);
|
StripTailDirSlashes(copy);
|
||||||
|
|
@ -157,7 +174,13 @@ bool Exists(const std::string& filename) {
|
||||||
|
|
||||||
int result = _wstat64(Common::UTF8ToUTF16W(copy).c_str(), &file_info);
|
int result = _wstat64(Common::UTF8ToUTF16W(copy).c_str(), &file_info);
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
int result = AndroidStorage::FileExists(filename) ? 0 : -1;
|
int result;
|
||||||
|
if (AndroidCanUseRawFS()) {
|
||||||
|
struct stat file_info;
|
||||||
|
result = stat(AndroidTranslateFilename(copy).c_str(), &file_info);
|
||||||
|
} else {
|
||||||
|
result = AndroidStorage::FileExists(filename) ? 0 : -1;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
struct stat file_info;
|
struct stat file_info;
|
||||||
int result = stat(copy.c_str(), &file_info);
|
int result = stat(copy.c_str(), &file_info);
|
||||||
|
|
@ -167,9 +190,6 @@ bool Exists(const std::string& filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsDirectory(const std::string& filename) {
|
bool IsDirectory(const std::string& filename) {
|
||||||
#if defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
|
||||||
return AndroidStorage::IsDirectory(filename);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string copy(filename);
|
std::string copy(filename);
|
||||||
StripTailDirSlashes(copy);
|
StripTailDirSlashes(copy);
|
||||||
|
|
@ -181,6 +201,14 @@ bool IsDirectory(const std::string& filename) {
|
||||||
copy += DIR_SEP_CHR;
|
copy += DIR_SEP_CHR;
|
||||||
|
|
||||||
int result = _wstat64(Common::UTF8ToUTF16W(copy).c_str(), &file_info);
|
int result = _wstat64(Common::UTF8ToUTF16W(copy).c_str(), &file_info);
|
||||||
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
|
struct stat file_info;
|
||||||
|
int result;
|
||||||
|
if (AndroidCanUseRawFS()) {
|
||||||
|
result = stat(AndroidTranslateFilename(copy).c_str(), &file_info);
|
||||||
|
} else {
|
||||||
|
return AndroidStorage::IsDirectory(filename);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
struct stat file_info;
|
struct stat file_info;
|
||||||
int result = stat(copy.c_str(), &file_info);
|
int result = stat(copy.c_str(), &file_info);
|
||||||
|
|
@ -239,9 +267,16 @@ bool Delete(const std::string& filename) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
if (!AndroidStorage::DeleteDocument(filename)) {
|
if (AndroidCanUseRawFS()) {
|
||||||
LOG_ERROR(Common_Filesystem, "unlink failed on {}", filename);
|
if (unlink(AndroidTranslateFilename(filename).c_str()) == -1) {
|
||||||
return false;
|
LOG_ERROR(Common_Filesystem, "unlink failed on {}: {}", filename, GetLastErrorMsg());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!AndroidStorage::DeleteDocument(filename)) {
|
||||||
|
LOG_ERROR(Common_Filesystem, "unlink failed on {}", filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (unlink(filename.c_str()) == -1) {
|
if (unlink(filename.c_str()) == -1) {
|
||||||
|
|
@ -266,23 +301,39 @@ bool CreateDir(const std::string& path) {
|
||||||
LOG_ERROR(Common_Filesystem, "CreateDirectory failed on {}: {}", path, error);
|
LOG_ERROR(Common_Filesystem, "CreateDirectory failed on {}: {}", path, error);
|
||||||
return false;
|
return false;
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
std::string directory = path;
|
if (AndroidCanUseRawFS()) {
|
||||||
std::string filename = path;
|
if (mkdir(AndroidTranslateFilename(path).c_str(), 0755) == 0)
|
||||||
if (Common::EndsWith(path, "/")) {
|
return true;
|
||||||
directory = GetParentPath(path);
|
|
||||||
filename = GetParentPath(path);
|
int err = errno;
|
||||||
}
|
|
||||||
directory = GetParentPath(directory);
|
if (err == EEXIST) {
|
||||||
filename = GetFilename(filename);
|
LOG_DEBUG(Common_Filesystem, "mkdir failed on {}: already exists", path);
|
||||||
// If directory path is empty, set it to root.
|
return true;
|
||||||
if (directory.empty()) {
|
}
|
||||||
directory = "/";
|
|
||||||
}
|
LOG_ERROR(Common_Filesystem, "mkdir failed on {}: {}", path, strerror(err));
|
||||||
if (!AndroidStorage::CreateDir(directory, filename)) {
|
|
||||||
LOG_ERROR(Common_Filesystem, "mkdir failed on {}", path);
|
|
||||||
return false;
|
return false;
|
||||||
};
|
} else {
|
||||||
return true;
|
std::string directory = path;
|
||||||
|
std::string filename = path;
|
||||||
|
if (Common::EndsWith(path, "/")) {
|
||||||
|
directory = GetParentPath(path);
|
||||||
|
filename = GetParentPath(path);
|
||||||
|
}
|
||||||
|
directory = GetParentPath(directory);
|
||||||
|
filename = GetFilename(filename);
|
||||||
|
// If directory path is empty, set it to root.
|
||||||
|
if (directory.empty()) {
|
||||||
|
directory = "/";
|
||||||
|
}
|
||||||
|
if (!AndroidStorage::CreateDir(directory, filename)) {
|
||||||
|
LOG_ERROR(Common_Filesystem, "mkdir failed on {}", path);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
if (mkdir(path.c_str(), 0755) == 0)
|
if (mkdir(path.c_str(), 0755) == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -353,8 +404,13 @@ bool DeleteDir(const std::string& filename) {
|
||||||
if (::RemoveDirectoryW(Common::UTF8ToUTF16W(filename).c_str()))
|
if (::RemoveDirectoryW(Common::UTF8ToUTF16W(filename).c_str()))
|
||||||
return true;
|
return true;
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
if (AndroidStorage::DeleteDocument(filename))
|
if (AndroidCanUseRawFS()) {
|
||||||
return true;
|
if (rmdir(AndroidTranslateFilename(filename).c_str()) == 0)
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (AndroidStorage::DeleteDocument(filename))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (rmdir(filename.c_str()) == 0)
|
if (rmdir(filename.c_str()) == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -372,16 +428,14 @@ bool Rename(const std::string& srcFullPath, const std::string& destFullPath) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
// srcFullPath and destFullPath are relative to the user directory
|
if (AndroidCanUseRawFS()) {
|
||||||
if (AndroidStorage::GetBuildFlavor() == AndroidStorage::AndroidBuildFlavors::GOOGLEPLAY) {
|
if (rename(AndroidTranslateFilename(srcFullPath).c_str(),
|
||||||
if (AndroidStorage::MoveAndRenameFile(srcFullPath, destFullPath))
|
AndroidTranslateFilename(destFullPath).c_str()) == 0) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
std::optional<std::string> userDirLocation = AndroidStorage::GetUserDirectory();
|
if (AndroidStorage::MoveAndRenameFile(srcFullPath, destFullPath)) {
|
||||||
if (userDirLocation && rename((*userDirLocation + srcFullPath).c_str(),
|
|
||||||
(*userDirLocation + destFullPath).c_str()) == 0) {
|
|
||||||
AndroidStorage::UpdateDocumentLocation(srcFullPath, destFullPath);
|
|
||||||
// ^ TODO: This shouldn't fail, but what should we do if it somehow does?
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -404,52 +458,62 @@ bool Copy(const std::string& srcFilename, const std::string& destFilename) {
|
||||||
LOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename,
|
LOG_ERROR(Common_Filesystem, "failed {} --> {}: {}", srcFilename, destFilename,
|
||||||
GetLastErrorMsg());
|
GetLastErrorMsg());
|
||||||
return false;
|
return false;
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
|
||||||
return AndroidStorage::CopyFile(srcFilename, std::string(GetParentPath(destFilename)),
|
|
||||||
std::string(GetFilename(destFilename)));
|
|
||||||
#else
|
#else
|
||||||
|
auto copy_files = [](const std::string& src, const std::string& dst) -> bool {
|
||||||
|
// Open input file
|
||||||
|
FILE* input = FOPEN(src.c_str(), "rb");
|
||||||
|
if (!input) {
|
||||||
|
LOG_ERROR(Common_Filesystem, "opening input failed {} --> {}: {}", src, dst,
|
||||||
|
GetLastErrorMsg());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SCOPE_EXIT({ FCLOSE(input); });
|
||||||
|
|
||||||
// Open input file
|
// open output file
|
||||||
FILE* input = FOPEN(srcFilename.c_str(), "rb");
|
FILE* output = FOPEN(dst.c_str(), "wb");
|
||||||
if (!input) {
|
if (!output) {
|
||||||
LOG_ERROR(Common_Filesystem, "opening input failed {} --> {}: {}", srcFilename,
|
LOG_ERROR(Common_Filesystem, "opening output failed {} --> {}: {}", src, dst,
|
||||||
destFilename, GetLastErrorMsg());
|
GetLastErrorMsg());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SCOPE_EXIT({ FCLOSE(input); });
|
SCOPE_EXIT({ FCLOSE(output); });
|
||||||
|
|
||||||
// open output file
|
// copy loop
|
||||||
FILE* output = FOPEN(destFilename.c_str(), "wb");
|
std::array<char, 1024> buffer;
|
||||||
if (!output) {
|
while (!FEOF(input)) {
|
||||||
LOG_ERROR(Common_Filesystem, "opening output failed {} --> {}: {}", srcFilename,
|
// read input
|
||||||
destFilename, GetLastErrorMsg());
|
std::size_t rnum = FREAD(buffer.data(), sizeof(char), buffer.size(), input);
|
||||||
return false;
|
if (rnum != buffer.size()) {
|
||||||
}
|
if (FERROR(input) != 0) {
|
||||||
SCOPE_EXIT({ FCLOSE(output); });
|
LOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}", src,
|
||||||
|
dst, GetLastErrorMsg());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// copy loop
|
// write output
|
||||||
std::array<char, 1024> buffer;
|
std::size_t wnum = FWRITE(buffer.data(), sizeof(char), rnum, output);
|
||||||
while (!FEOF(input)) {
|
if (wnum != rnum) {
|
||||||
// read input
|
LOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", src, dst,
|
||||||
std::size_t rnum = FREAD(buffer.data(), sizeof(char), buffer.size(), input);
|
GetLastErrorMsg());
|
||||||
if (rnum != buffer.size()) {
|
|
||||||
if (FERROR(input) != 0) {
|
|
||||||
LOG_ERROR(Common_Filesystem, "failed reading from source, {} --> {}: {}",
|
|
||||||
srcFilename, destFilename, GetLastErrorMsg());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// write output
|
return true;
|
||||||
std::size_t wnum = FWRITE(buffer.data(), sizeof(char), rnum, output);
|
};
|
||||||
if (wnum != rnum) {
|
|
||||||
LOG_ERROR(Common_Filesystem, "failed writing to output, {} --> {}: {}", srcFilename,
|
|
||||||
destFilename, GetLastErrorMsg());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
#if defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
|
if (AndroidCanUseRawFS()) {
|
||||||
|
return copy_files(AndroidTranslateFilename(srcFilename),
|
||||||
|
AndroidTranslateFilename(destFilename));
|
||||||
|
} else {
|
||||||
|
return AndroidStorage::CopyFile(srcFilename, std::string(GetParentPath(destFilename)),
|
||||||
|
std::string(GetFilename(destFilename)));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return copy_files(srcFilename, destFilename);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -470,9 +534,15 @@ u64 GetSize(const std::string& filename) {
|
||||||
struct _stat64 buf;
|
struct _stat64 buf;
|
||||||
if (_wstat64(Common::UTF8ToUTF16W(filename).c_str(), &buf) == 0)
|
if (_wstat64(Common::UTF8ToUTF16W(filename).c_str(), &buf) == 0)
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
u64 result = AndroidStorage::GetSize(filename);
|
if (AndroidCanUseRawFS()) {
|
||||||
LOG_TRACE(Common_Filesystem, "{}: {}", filename, result);
|
if (stat(AndroidTranslateFilename(filename).c_str(), &buf) == 0) {
|
||||||
return result;
|
return buf.st_size;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
u64 result = AndroidStorage::GetSize(filename);
|
||||||
|
LOG_TRACE(Common_Filesystem, "{}: {}", filename, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (stat(filename.c_str(), &buf) == 0)
|
if (stat(filename.c_str(), &buf) == 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -520,68 +590,97 @@ bool CreateEmptyFile(const std::string& filename) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
std::optional<std::vector<std::string>> ListDirectoryEntries(const std::string& directory) {
|
||||||
|
std::vector<std::string> entries;
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW ffd;
|
||||||
|
const std::wstring search_path = Common::UTF8ToUTF16W(directory + "\\*");
|
||||||
|
|
||||||
|
HANDLE handle = FindFirstFileW(search_path.c_str(), &ffd);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
entries.emplace_back(Common::UTF16ToUTF8(ffd.cFileName));
|
||||||
|
} while (FindNextFileW(handle, &ffd) != 0);
|
||||||
|
|
||||||
|
FindClose(handle);
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
|
|
||||||
|
std::optional<std::vector<std::string>> ListDirectoryEntries(const std::string& directory) {
|
||||||
|
if (AndroidCanUseRawFS()) {
|
||||||
|
std::vector<std::string> entries;
|
||||||
|
|
||||||
|
DIR* dirp = opendir(AndroidTranslateFilename(directory).c_str());
|
||||||
|
if (!dirp)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
while (dirent* entry = readdir(dirp)) {
|
||||||
|
entries.emplace_back(entry->d_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dirp);
|
||||||
|
return entries;
|
||||||
|
} else {
|
||||||
|
return AndroidStorage::GetFilesName(directory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
std::optional<std::vector<std::string>> ListDirectoryEntries(const std::string& directory) {
|
||||||
|
std::vector<std::string> entries;
|
||||||
|
|
||||||
|
DIR* dirp = opendir(directory.c_str());
|
||||||
|
if (!dirp)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
while (dirent* entry = readdir(dirp)) {
|
||||||
|
entries.emplace_back(entry->d_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dirp);
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory,
|
bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory,
|
||||||
DirectoryEntryCallable callback) {
|
DirectoryEntryCallable callback) {
|
||||||
LOG_TRACE(Common_Filesystem, "directory {}", directory);
|
LOG_TRACE(Common_Filesystem, "directory {}", directory);
|
||||||
|
|
||||||
// How many files + directories we found
|
const auto entries = ListDirectoryEntries(directory);
|
||||||
u64 found_entries = 0;
|
if (!entries.has_value()) {
|
||||||
|
|
||||||
// Save the status of callback function
|
|
||||||
bool callback_error = false;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// Find the first file in the directory.
|
|
||||||
WIN32_FIND_DATAW ffd;
|
|
||||||
|
|
||||||
HANDLE handle_find = FindFirstFileW(Common::UTF8ToUTF16W(directory + "\\*").c_str(), &ffd);
|
|
||||||
if (handle_find == INVALID_HANDLE_VALUE) {
|
|
||||||
FindClose(handle_find);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// windows loop
|
|
||||||
do {
|
|
||||||
const std::string virtual_name(Common::UTF16ToUTF8(ffd.cFileName));
|
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
|
||||||
// android loop
|
|
||||||
auto result = AndroidStorage::GetFilesName(directory);
|
|
||||||
for (auto virtual_name : result) {
|
|
||||||
#else
|
|
||||||
DIR* dirp = opendir(directory.c_str());
|
|
||||||
if (!dirp)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// non windows loop
|
u64 found_entries = 0;
|
||||||
while (struct dirent* result = readdir(dirp)) {
|
|
||||||
const std::string virtual_name(result->d_name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
for (const std::string& virtual_name : *entries) {
|
||||||
if (virtual_name == "." || virtual_name == "..")
|
if (virtual_name == "." || virtual_name == "..")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
u64 ret_entries = 0;
|
u64 ret_entries = 0;
|
||||||
if (!callback(&ret_entries, directory, virtual_name)) {
|
if (!callback(&ret_entries, directory, virtual_name))
|
||||||
callback_error = true;
|
return false;
|
||||||
break;
|
|
||||||
}
|
|
||||||
found_entries += ret_entries;
|
found_entries += ret_entries;
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
} while (FindNextFileW(handle_find, &ffd) != 0);
|
|
||||||
FindClose(handle_find);
|
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
}
|
|
||||||
closedir(dirp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (callback_error)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// num_entries_out is allowed to be specified nullptr, in which case we shouldn't try to set it
|
// num_entries_out is allowed to be specified nullptr, in which case we shouldn't try to set it
|
||||||
if (num_entries_out != nullptr)
|
if (num_entries_out)
|
||||||
*num_entries_out = found_entries;
|
*num_entries_out = found_entries;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -658,48 +757,39 @@ bool DeleteDirRecursively(const std::string& directory, unsigned int recursion)
|
||||||
|
|
||||||
void CopyDir([[maybe_unused]] const std::string& source_path,
|
void CopyDir([[maybe_unused]] const std::string& source_path,
|
||||||
[[maybe_unused]] const std::string& dest_path) {
|
[[maybe_unused]] const std::string& dest_path) {
|
||||||
#ifndef _WIN32
|
|
||||||
if (source_path == dest_path)
|
if (source_path == dest_path)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!FileUtil::Exists(source_path))
|
if (!FileUtil::Exists(source_path))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!FileUtil::Exists(dest_path))
|
if (!FileUtil::Exists(dest_path))
|
||||||
FileUtil::CreateFullPath(dest_path);
|
FileUtil::CreateFullPath(dest_path);
|
||||||
|
|
||||||
#if defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
const auto entries = ListDirectoryEntries(source_path);
|
||||||
auto result = AndroidStorage::GetFilesName(source_path);
|
if (!entries.has_value() || (*entries).empty())
|
||||||
for (auto virtualName : result) {
|
|
||||||
#else
|
|
||||||
DIR* dirp = opendir(source_path.c_str());
|
|
||||||
if (!dirp)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (struct dirent* result = readdir(dirp)) {
|
for (const std::string& virtual_name : *entries) {
|
||||||
const std::string virtualName(result->d_name);
|
if (virtual_name == "." || virtual_name == "..")
|
||||||
#endif // ANDROID
|
|
||||||
|
|
||||||
// check for "." and ".."
|
|
||||||
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
|
|
||||||
((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0')))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string source, dest;
|
std::string source = source_path + virtual_name;
|
||||||
source = source_path + virtualName;
|
std::string dest = dest_path + virtual_name;
|
||||||
dest = dest_path + virtualName;
|
|
||||||
if (IsDirectory(source)) {
|
if (IsDirectory(source)) {
|
||||||
source += '/';
|
source += '/';
|
||||||
dest += '/';
|
dest += '/';
|
||||||
|
|
||||||
if (!FileUtil::Exists(dest))
|
if (!FileUtil::Exists(dest))
|
||||||
FileUtil::CreateFullPath(dest);
|
FileUtil::CreateFullPath(dest);
|
||||||
CopyDir(source, dest);
|
|
||||||
} else if (!FileUtil::Exists(dest))
|
|
||||||
FileUtil::Copy(source, dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !(defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS))
|
CopyDir(source, dest);
|
||||||
closedir(dirp);
|
} else {
|
||||||
#endif // ANDROID
|
if (!FileUtil::Exists(dest))
|
||||||
#endif // _WIN32
|
FileUtil::Copy(source, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> GetCurrentDir() {
|
std::optional<std::string> GetCurrentDir() {
|
||||||
|
|
@ -1234,34 +1324,37 @@ bool IOFile::Open() {
|
||||||
m_good = m_file != nullptr;
|
m_good = m_file != nullptr;
|
||||||
|
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
// Check whether filepath is startsWith content
|
if (AndroidCanUseRawFS()) {
|
||||||
AndroidStorage::AndroidOpenMode android_open_mode = AndroidStorage::ParseOpenmode(openmode);
|
m_file = FOPEN(AndroidTranslateFilename(filename).c_str(), openmode.c_str());
|
||||||
if (android_open_mode == AndroidStorage::AndroidOpenMode::WRITE ||
|
} else {
|
||||||
android_open_mode == AndroidStorage::AndroidOpenMode::READ_WRITE ||
|
// Check whether filepath is startsWith content
|
||||||
android_open_mode == AndroidStorage::AndroidOpenMode::WRITE_APPEND ||
|
AndroidStorage::AndroidOpenMode android_open_mode = AndroidStorage::ParseOpenmode(openmode);
|
||||||
android_open_mode == AndroidStorage::AndroidOpenMode::WRITE_TRUNCATE ||
|
if (android_open_mode == AndroidStorage::AndroidOpenMode::WRITE ||
|
||||||
android_open_mode == AndroidStorage::AndroidOpenMode::READ_WRITE_TRUNCATE ||
|
android_open_mode == AndroidStorage::AndroidOpenMode::READ_WRITE ||
|
||||||
android_open_mode == AndroidStorage::AndroidOpenMode::READ_WRITE_APPEND) {
|
android_open_mode == AndroidStorage::AndroidOpenMode::WRITE_APPEND ||
|
||||||
if (!FileUtil::Exists(filename)) {
|
android_open_mode == AndroidStorage::AndroidOpenMode::WRITE_TRUNCATE ||
|
||||||
std::string directory(GetParentPath(filename));
|
android_open_mode == AndroidStorage::AndroidOpenMode::READ_WRITE_TRUNCATE ||
|
||||||
std::string display_name(GetFilename(filename));
|
android_open_mode == AndroidStorage::AndroidOpenMode::READ_WRITE_APPEND) {
|
||||||
if (!AndroidStorage::CreateFile(directory, display_name)) {
|
if (!FileUtil::Exists(filename)) {
|
||||||
m_good = m_file != nullptr;
|
std::string directory(GetParentPath(filename));
|
||||||
return m_good;
|
std::string display_name(GetFilename(filename));
|
||||||
|
if (!AndroidStorage::CreateFile(directory, display_name)) {
|
||||||
|
m_good = m_file != nullptr;
|
||||||
|
return m_good;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_fd = AndroidStorage::OpenContentUri(filename, android_open_mode);
|
||||||
|
if (m_fd != -1) {
|
||||||
|
int error_num = 0;
|
||||||
|
m_file = fdopen(m_fd, openmode.c_str());
|
||||||
|
error_num = errno;
|
||||||
|
if (error_num != 0 && m_file == nullptr) {
|
||||||
|
LOG_ERROR(Common_Filesystem, "Error on file: {}, error: {}", filename,
|
||||||
|
strerror(error_num));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_fd = AndroidStorage::OpenContentUri(filename, android_open_mode);
|
|
||||||
if (m_fd != -1) {
|
|
||||||
int error_num = 0;
|
|
||||||
m_file = fdopen(m_fd, openmode.c_str());
|
|
||||||
error_num = errno;
|
|
||||||
if (error_num != 0 && m_file == nullptr) {
|
|
||||||
LOG_ERROR(Common_Filesystem, "Error on file: {}, error: {}", filename,
|
|
||||||
strerror(error_num));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_good = m_file != nullptr;
|
m_good = m_file != nullptr;
|
||||||
#else
|
#else
|
||||||
m_file = FOPEN(filename.c_str(), openmode.c_str());
|
m_file = FOPEN(filename.c_str(), openmode.c_str());
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue