diff --git a/rpcs3/Emu/Cell/Modules/cellGame.cpp b/rpcs3/Emu/Cell/Modules/cellGame.cpp index 774dccdd45..10009f4ae3 100644 --- a/rpcs3/Emu/Cell/Modules/cellGame.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGame.cpp @@ -453,7 +453,7 @@ error_code cellGameContentPermit(vm::ptr contentInfoPa // Make temporary directory persistent const auto vdir = vfs::get(dir); - if (fs::rename(prm->temp, vdir, false)) + if (vfs::host::rename(prm->temp, vdir, false)) { cellGame.success("cellGameContentPermit(): directory '%s' has been created", dir); } diff --git a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp index 1804267027..91b96f78e2 100644 --- a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp @@ -934,19 +934,16 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v fs::remove_all(old_path, false); // Backup old savedata - while (!fs::rename(dir_path, old_path, true)) + if (!vfs::host::rename(dir_path, old_path, true)) { - // Try to ignore access error in order to prevent spurious failure - if (Emu.IsStopped() || fs::g_tls_error != fs::error::acces) - fmt::throw_exception("Failed to move directory %s (%s)", dir_path, fs::g_tls_error); + fmt::throw_exception("Failed to move directory %s (%s)", dir_path, fs::g_tls_error); } // Commit new savedata - while (!fs::rename(new_path, dir_path, false)) + if (!vfs::host::rename(new_path, dir_path, false)) { // TODO: handle the case when only commit failed at the next save load - if (Emu.IsStopped() || fs::g_tls_error != fs::error::acces) - fmt::throw_exception("Failed to move directory %s (%s)", new_path, fs::g_tls_error); + fmt::throw_exception("Failed to move directory %s (%s)", new_path, fs::g_tls_error); } // Remove backup again (TODO: may be changed to persistent backup implementation) diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index 475aa3155c..02054e0504 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -774,7 +774,7 @@ error_code sys_fs_rename(vm::cptr from, vm::cptr to) return CELL_ENOTMOUNTED; } - if (!fs::rename(local_from, local_to, false)) + if (!vfs::host::rename(local_from, local_to, false)) { switch (auto error = fs::g_tls_error) { diff --git a/rpcs3/Emu/VFS.cpp b/rpcs3/Emu/VFS.cpp index d8ae90cf2e..4535a3158d 100644 --- a/rpcs3/Emu/VFS.cpp +++ b/rpcs3/Emu/VFS.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "IdManager.h" +#include "System.h" #include "VFS.h" #include "Utilities/mutex.h" @@ -447,3 +448,17 @@ std::string vfs::unescape(std::string_view path) return result; } + +bool vfs::host::rename(const std::string& from, const std::string& to, bool overwrite) +{ + while (!fs::rename(from, to, overwrite)) + { + // Try to ignore access error in order to prevent spurious failure + if (Emu.IsStopped() || fs::g_tls_error != fs::error::acces) + { + return false; + } + } + + return true; +} diff --git a/rpcs3/Emu/VFS.h b/rpcs3/Emu/VFS.h index b4dc298e55..bb546c097b 100644 --- a/rpcs3/Emu/VFS.h +++ b/rpcs3/Emu/VFS.h @@ -17,4 +17,11 @@ namespace vfs // Invert escape operation std::string unescape(std::string_view path); + + // Functions in this namespace operate on host filepaths, similar to fs:: + namespace host + { + // Call fs::rename with retry on access error + bool rename(const std::string& from, const std::string& to, bool overwrite); + } }