mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 05:09:34 -06:00
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:
@ -8,6 +8,8 @@
|
|||||||
#include "Common/File.h"
|
#include "Common/File.h"
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
#include "Common/MsgHandler.h"
|
||||||
|
|
||||||
#include "Core/IOS/FS/HostBackend/FS.h"
|
#include "Core/IOS/FS/HostBackend/FS.h"
|
||||||
|
|
||||||
namespace IOS::HLE::FS
|
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)
|
// - The Beatles: Rock Band (saving doesn't work)
|
||||||
|
|
||||||
// Check if the file has already been opened.
|
// Check if the file has already been opened.
|
||||||
std::shared_ptr<File::IOFile> file;
|
|
||||||
auto search = m_open_files.find(host_path);
|
auto search = m_open_files.find(host_path);
|
||||||
if (search != m_open_files.end())
|
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.
|
const bool try_again =
|
||||||
auto deleter = [this, host_path](File::IOFile* ptr) {
|
PanicYesNo("File \"%s\" could not be opened!\n"
|
||||||
delete ptr; // IOFile's deconstructor closes the file.
|
"This may happen with improper permissions or use by another process.\n"
|
||||||
m_open_files.erase(host_path); // erase the weak pointer from the list of open files.
|
"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
|
if (!try_again)
|
||||||
// read/write functions below
|
{
|
||||||
file = std::shared_ptr<File::IOFile>(new File::IOFile(host_path, "r+b"),
|
// We've failed to open the file:
|
||||||
deleter); // Use the custom deleter from above.
|
ERROR_LOG(IOS_FS, "OpenHostFile %s", host_path.c_str());
|
||||||
|
return nullptr;
|
||||||
// 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;
|
|
||||||
|
// 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::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_ptr);
|
||||||
|
|
||||||
|
return file_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<FileHandle> HostFileSystem::OpenFile(Uid, Gid, const std::string& path, Mode mode)
|
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);
|
handle->host_file = OpenHostFile(host_path);
|
||||||
|
if (!handle->host_file)
|
||||||
|
{
|
||||||
|
*handle = Handle{};
|
||||||
|
return ResultCode::AccessDenied;
|
||||||
|
}
|
||||||
|
|
||||||
handle->wii_path = path;
|
handle->wii_path = path;
|
||||||
handle->mode = mode;
|
handle->mode = mode;
|
||||||
handle->file_offset = 0;
|
handle->file_offset = 0;
|
||||||
|
Reference in New Issue
Block a user