Permalink
Browse files

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.
  • Loading branch information...
jordan-woyak committed Dec 2, 2018
1 parent 8d20a17 commit 122ce2878641acffb7233a60964c3b2643d08131
Showing with 41 additions and 17 deletions.
  1. +41 −17 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<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"))
{
// 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.
// Store a weak pointer to our newly opened file in the cache.
m_open_files[host_path] = std::weak_ptr<File::IOFile>(file);
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;
}
}
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)
@@ -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;

0 comments on commit 122ce28

Please sign in to comment.