From 122ce2878641acffb7233a60964c3b2643d08131 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 2 Dec 2018 14:39:58 -0600 Subject: [PATCH] Present an error message when failing to open a file that should exist. This could happen with savestate loads, permission issues, or use by other processes. Prior to this Dolphin assumed any existing file could be opened and crashes from invalid variant access. Failing to open a file during savestate load will likely still crash but at least the user will know why. --- Source/Core/Core/IOS/FS/HostBackend/File.cpp | 56 ++++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/Source/Core/Core/IOS/FS/HostBackend/File.cpp b/Source/Core/Core/IOS/FS/HostBackend/File.cpp index 661413300d..1cea8bd64e 100644 --- a/Source/Core/Core/IOS/FS/HostBackend/File.cpp +++ b/Source/Core/Core/IOS/FS/HostBackend/File.cpp @@ -8,6 +8,8 @@ #include "Common/File.h" #include "Common/FileUtil.h" #include "Common/Logging/Log.h" +#include "Common/MsgHandler.h" + #include "Core/IOS/FS/HostBackend/FS.h" namespace IOS::HLE::FS @@ -32,29 +34,45 @@ std::shared_ptr HostFileSystem::OpenHostFile(const std::string& ho // - The Beatles: Rock Band (saving doesn't work) // Check if the file has already been opened. - std::shared_ptr file; auto search = m_open_files.find(host_path); if (search != m_open_files.end()) { - file = search->second.lock(); // Lock a shared pointer to use. + // Lock a shared pointer to use. + return search->second.lock(); } - else + + // All files are opened read/write. Actual access rights will be controlled per handle by the + // read/write functions below + File::IOFile file; + while (!file.Open(host_path, "r+b")) { - // This code will be called when all references to the shared pointer below have been removed. - auto deleter = [this, host_path](File::IOFile* ptr) { - delete ptr; // IOFile's deconstructor closes the file. - m_open_files.erase(host_path); // erase the weak pointer from the list of open files. - }; + const bool try_again = + PanicYesNo("File \"%s\" could not be opened!\n" + "This may happen with improper permissions or use by another process.\n" + "Press \"Yes\" to make another attempt.", + host_path.c_str()); - // All files are opened read/write. Actual access rights will be controlled per handle by the - // read/write functions below - file = std::shared_ptr(new File::IOFile(host_path, "r+b"), - deleter); // Use the custom deleter from above. - - // Store a weak pointer to our newly opened file in the cache. - m_open_files[host_path] = std::weak_ptr(file); + if (!try_again) + { + // We've failed to open the file: + ERROR_LOG(IOS_FS, "OpenHostFile %s", host_path.c_str()); + return nullptr; + } } - return file; + + // This code will be called when all references to the shared pointer below have been removed. + auto deleter = [this, host_path](File::IOFile* ptr) { + delete ptr; // IOFile's deconstructor closes the file. + m_open_files.erase(host_path); // erase the weak pointer from the list of open files. + }; + + // Use the custom deleter from above. + std::shared_ptr file_ptr(new File::IOFile(std::move(file)), deleter); + + // Store a weak pointer to our newly opened file in the cache. + m_open_files[host_path] = std::weak_ptr(file_ptr); + + return file_ptr; } Result HostFileSystem::OpenFile(Uid, Gid, const std::string& path, Mode mode) @@ -71,6 +89,12 @@ Result HostFileSystem::OpenFile(Uid, Gid, const std::string& path, M } handle->host_file = OpenHostFile(host_path); + if (!handle->host_file) + { + *handle = Handle{}; + return ResultCode::AccessDenied; + } + handle->wii_path = path; handle->mode = mode; handle->file_offset = 0;