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.
This commit is contained in:
parent
8d20a173f0
commit
122ce28786
|
@ -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<File::IOFile> 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::IOFile> 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"))
|
||||
{
|
||||
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());
|
||||
|
||||
if (!try_again)
|
||||
{
|
||||
// We've failed to open the file:
|
||||
ERROR_LOG(IOS_FS, "OpenHostFile %s", host_path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
};
|
||||
|
||||
// All files are opened read/write. Actual access rights will be controlled per handle by the
|
||||
// read/write functions below
|
||||
file = std::shared_ptr<File::IOFile>(new File::IOFile(host_path, "r+b"),
|
||||
deleter); // Use the custom deleter from above.
|
||||
// Use the custom deleter from above.
|
||||
std::shared_ptr<File::IOFile> 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::IOFile>(file);
|
||||
}
|
||||
return file;
|
||||
m_open_files[host_path] = std::weak_ptr<File::IOFile>(file_ptr);
|
||||
|
||||
return file_ptr;
|
||||
}
|
||||
|
||||
Result<FileHandle> HostFileSystem::OpenFile(Uid, Gid, const std::string& path, Mode mode)
|
||||
|
@ -71,6 +89,12 @@ Result<FileHandle> 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;
|
||||
|
|
Loading…
Reference in New Issue