mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-06 02:33:44 -04:00
file_util: Fix file behaviour on Windows (#1841)
This commit is contained in:
parent
ced1ec0112
commit
1e0df67cc4
4 changed files with 69 additions and 33 deletions
|
|
@ -211,10 +211,33 @@ bool Delete(const std::string& filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!DeleteFileW(Common::UTF8ToUTF16W(filename).c_str())) {
|
// On windows, if we delete a file with an open handle (pending to be deleted) and
|
||||||
LOG_ERROR(Common_Filesystem, "DeleteFile failed on {}: {}", filename, GetLastErrorMsg());
|
// then try to open the same file name again, it will fail. On linux this doesn't happen
|
||||||
return false;
|
// as the new file will be a different inode, even if it has the same file name.
|
||||||
|
// The 3ds is linux-like, so to emulate this behaviour we need to rename the file
|
||||||
|
// first to an unique name then mark it for deletion. This way we can open new files
|
||||||
|
// with the same name. Once all handles of the old file are closed, the old file will be
|
||||||
|
// finally deleted.
|
||||||
|
static std::atomic<uint64_t> counter{0};
|
||||||
|
|
||||||
|
const std::wstring wfilename = Common::UTF8ToUTF16W(filename);
|
||||||
|
const DWORD pid = GetCurrentProcessId();
|
||||||
|
const uint64_t id = counter++;
|
||||||
|
|
||||||
|
std::wstring deleted_path =
|
||||||
|
wfilename + L".deleted." + std::to_wstring(pid) + L"." + std::to_wstring(id);
|
||||||
|
|
||||||
|
// Rename first
|
||||||
|
if (MoveFileExW(wfilename.c_str(), deleted_path.c_str(), MOVEFILE_REPLACE_EXISTING)) {
|
||||||
|
// Then mark file for deletion
|
||||||
|
DeleteFileW(deleted_path.c_str());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_ERROR(Common_Filesystem, "Rename to deleted path failed on {}: {}", filename,
|
||||||
|
GetLastErrorMsg());
|
||||||
|
|
||||||
|
return false;
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
if (!AndroidStorage::DeleteDocument(filename)) {
|
if (!AndroidStorage::DeleteDocument(filename)) {
|
||||||
LOG_ERROR(Common_Filesystem, "unlink failed on {}", filename);
|
LOG_ERROR(Common_Filesystem, "unlink failed on {}", filename);
|
||||||
|
|
@ -344,9 +367,10 @@ bool DeleteDir(const std::string& filename) {
|
||||||
bool Rename(const std::string& srcFullPath, const std::string& destFullPath) {
|
bool Rename(const std::string& srcFullPath, const std::string& destFullPath) {
|
||||||
LOG_TRACE(Common_Filesystem, "{} --> {}", srcFullPath, destFullPath);
|
LOG_TRACE(Common_Filesystem, "{} --> {}", srcFullPath, destFullPath);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (_wrename(Common::UTF8ToUTF16W(srcFullPath).c_str(),
|
if (MoveFileExW(Common::UTF8ToUTF16W(srcFullPath).c_str(),
|
||||||
Common::UTF8ToUTF16W(destFullPath).c_str()) == 0)
|
Common::UTF8ToUTF16W(destFullPath).c_str(), MOVEFILE_REPLACE_EXISTING)) {
|
||||||
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
|
// srcFullPath and destFullPath are relative to the user directory
|
||||||
if (AndroidStorage::GetBuildFlavor() == AndroidStorage::AndroidBuildFlavors::GOOGLEPLAY) {
|
if (AndroidStorage::GetBuildFlavor() == AndroidStorage::AndroidBuildFlavors::GOOGLEPLAY) {
|
||||||
|
|
@ -1167,11 +1191,46 @@ bool IOFile::Open() {
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (flags == 0) {
|
// Open with FILE_SHARE_READ, FILE_SHARE_WRITE and FILE_SHARE_DELETE
|
||||||
flags = _SH_DENYNO;
|
// flags. This mimics linux behaviour as much as possible, which
|
||||||
|
// the 3DS also does.
|
||||||
|
|
||||||
|
const std::wstring wfilename = Common::UTF8ToUTF16W(filename);
|
||||||
|
|
||||||
|
DWORD access = 0;
|
||||||
|
DWORD creation = OPEN_EXISTING;
|
||||||
|
|
||||||
|
if (openmode.find("r") != std::string::npos)
|
||||||
|
access |= GENERIC_READ;
|
||||||
|
if (openmode.find("w") != std::string::npos) {
|
||||||
|
access |= GENERIC_WRITE;
|
||||||
|
creation = CREATE_ALWAYS;
|
||||||
}
|
}
|
||||||
m_file = _wfsopen(Common::UTF8ToUTF16W(filename).c_str(),
|
if (openmode.find("a") != std::string::npos) {
|
||||||
Common::UTF8ToUTF16W(openmode).c_str(), flags);
|
access |= FILE_APPEND_DATA;
|
||||||
|
creation = OPEN_ALWAYS;
|
||||||
|
}
|
||||||
|
if (openmode.find("+") != std::string::npos) {
|
||||||
|
access |= GENERIC_READ | GENERIC_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE h = CreateFileW(wfilename.c_str(), access,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
|
creation, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
|
||||||
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
|
m_good = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = _open_osfhandle(reinterpret_cast<intptr_t>(h), 0);
|
||||||
|
if (fd == -1) {
|
||||||
|
CloseHandle(h);
|
||||||
|
m_good = false;
|
||||||
|
return m_good;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_file = _fdopen(fd, openmode.c_str());
|
||||||
m_good = m_file != nullptr;
|
m_good = m_file != nullptr;
|
||||||
|
|
||||||
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
#elif defined(ANDROID) && !defined(HAVE_LIBRETRO_VFS)
|
||||||
|
|
|
||||||
|
|
@ -469,7 +469,6 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
|
||||||
m_emu_window = &emu_window;
|
m_emu_window = &emu_window;
|
||||||
m_secondary_window = secondary_window;
|
m_secondary_window = secondary_window;
|
||||||
m_filepath = filepath;
|
m_filepath = filepath;
|
||||||
self_delete_pending = false;
|
|
||||||
|
|
||||||
// Reset counters and set time origin to current frame
|
// Reset counters and set time origin to current frame
|
||||||
[[maybe_unused]] const PerfStats::Results result = GetAndResetPerfStats();
|
[[maybe_unused]] const PerfStats::Results result = GetAndResetPerfStats();
|
||||||
|
|
@ -721,10 +720,6 @@ void System::Shutdown(bool is_deserializing) {
|
||||||
|
|
||||||
memory.reset();
|
memory.reset();
|
||||||
|
|
||||||
if (self_delete_pending)
|
|
||||||
FileUtil::Delete(m_filepath);
|
|
||||||
self_delete_pending = false;
|
|
||||||
|
|
||||||
LOG_DEBUG(Core, "Shutdown OK");
|
LOG_DEBUG(Core, "Shutdown OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -366,15 +366,6 @@ public:
|
||||||
|
|
||||||
bool LoadStateBuffer(std::vector<u8> buffer);
|
bool LoadStateBuffer(std::vector<u8> buffer);
|
||||||
|
|
||||||
/// Self delete ncch
|
|
||||||
bool SetSelfDelete(const std::string& file) {
|
|
||||||
if (m_filepath == file) {
|
|
||||||
self_delete_pending = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Applies any changes to settings to this core instance.
|
/// Applies any changes to settings to this core instance.
|
||||||
void ApplySettings();
|
void ApplySettings();
|
||||||
|
|
||||||
|
|
@ -480,7 +471,6 @@ private:
|
||||||
std::string m_chainloadpath;
|
std::string m_chainloadpath;
|
||||||
std::optional<u8> m_mem_mode;
|
std::optional<u8> m_mem_mode;
|
||||||
u64 title_id;
|
u64 title_id;
|
||||||
bool self_delete_pending;
|
|
||||||
|
|
||||||
std::mutex signal_mutex;
|
std::mutex signal_mutex;
|
||||||
Signal current_signal;
|
Signal current_signal;
|
||||||
|
|
|
||||||
|
|
@ -916,15 +916,7 @@ bool CIAFile::Close() {
|
||||||
if (abort) {
|
if (abort) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
FileUtil::Delete(GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index));
|
||||||
// If the file to delete is the current launched rom, signal the system to delete
|
|
||||||
// the current rom instead of deleting it now, once all the handles to the file
|
|
||||||
// are closed.
|
|
||||||
std::string to_delete =
|
|
||||||
GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index);
|
|
||||||
if (!system.IsPoweredOn() || !system.SetSelfDelete(to_delete)) {
|
|
||||||
FileUtil::Delete(to_delete);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileUtil::Delete(old_tmd_path);
|
FileUtil::Delete(old_tmd_path);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue