mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-31 20:41:45 +01:00
sceNpTrophyRegisterContext: Atomically create trophy data
This commit is contained in:
parent
a50ea09053
commit
3a96d99187
@ -628,7 +628,8 @@ namespace fs
|
||||
template <typename... Args>
|
||||
bool write_file(const std::string& path, bs_t<fs::open_mode> mode, const Args&... args)
|
||||
{
|
||||
if (fs::file f{path, mode})
|
||||
// Always use write flag, remove read flag
|
||||
if (fs::file f{path, mode + fs::write - fs::read})
|
||||
{
|
||||
// Write args sequentially
|
||||
(f.write(args), ...);
|
||||
|
@ -701,6 +701,11 @@ std::string vfs::unescape(std::string_view name)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string vfs::host::hash_path(const std::string& path, const std::string& dev_root)
|
||||
{
|
||||
return fmt::format(u8"%s/$%s%s", dev_root, fmt::base57(std::hash<std::string>()(path)), fmt::base57(__rdtsc()));
|
||||
}
|
||||
|
||||
bool vfs::host::rename(const std::string& from, const std::string& to, bool overwrite)
|
||||
{
|
||||
while (!fs::rename(from, to, overwrite))
|
||||
@ -725,7 +730,7 @@ bool vfs::host::unlink(const std::string& path, const std::string& dev_root)
|
||||
else
|
||||
{
|
||||
// Rename to special dummy name which will be ignored by VFS (but opened file handles can still read or write it)
|
||||
const std::string dummy = fmt::format(u8"%s/$%s%s", dev_root, fmt::base57(std::hash<std::string>()(path)), fmt::base57(__rdtsc()));
|
||||
const std::string dummy = hash_path(path, dev_root);
|
||||
|
||||
if (!fs::rename(path, dummy, true))
|
||||
{
|
||||
@ -755,7 +760,7 @@ bool vfs::host::remove_all(const std::string& path, const std::string& dev_root,
|
||||
if (remove_root)
|
||||
{
|
||||
// Rename to special dummy folder which will be ignored by VFS (but opened file handles can still read or write it)
|
||||
const std::string dummy = fmt::format(u8"%s/$%s%s", dev_root, fmt::base57(std::hash<std::string>()(path)), fmt::base57(__rdtsc()));
|
||||
const std::string dummy = hash_path(path, dev_root);
|
||||
|
||||
if (!vfs::host::rename(path, dummy, false))
|
||||
{
|
||||
|
@ -21,6 +21,8 @@ namespace vfs
|
||||
// Functions in this namespace operate on host filepaths, similar to fs::
|
||||
namespace host
|
||||
{
|
||||
std::string hash_path(const std::string& path, const std::string& dev_root);
|
||||
|
||||
// Call fs::rename with retry on access error
|
||||
bool rename(const std::string& from, const std::string& to, bool overwrite);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/VFS.h"
|
||||
#include "Emu/System.h"
|
||||
#include "TRP.h"
|
||||
#include "Crypto/sha1.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
@ -15,27 +16,58 @@ bool TRPLoader::Install(const std::string& dest, bool show)
|
||||
{
|
||||
if (!trp_f)
|
||||
{
|
||||
fs::g_tls_error = fs::error::noent;
|
||||
return false;
|
||||
}
|
||||
|
||||
fs::g_tls_error = {};
|
||||
|
||||
const std::string& local_path = vfs::get(dest);
|
||||
|
||||
if (!fs::is_dir(local_path) && !fs::create_dir(local_path))
|
||||
const auto temp = vfs::host::hash_path(local_path, Emu.GetHddDir()) + '/';
|
||||
|
||||
if (!fs::create_dir(temp))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<char> buffer(65536);
|
||||
|
||||
bool success = true;
|
||||
for (const TRPEntry& entry : m_entries)
|
||||
{
|
||||
trp_f.seek(entry.offset);
|
||||
buffer.resize(entry.size);
|
||||
if (!trp_f.read(buffer)) continue; // ???
|
||||
fs::file(local_path + '/' + entry.name, fs::rewrite).write(buffer);
|
||||
|
||||
// Create the file in the temporary directory
|
||||
success = fs::write_file(temp + vfs::escape(entry.name), fs::create + fs::excl, buffer);
|
||||
if (!success)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if (success)
|
||||
{
|
||||
success = vfs::host::remove_all(local_path, Emu.GetHddDir(), true);
|
||||
|
||||
if (success)
|
||||
{
|
||||
// Atomically create trophy data (overwrite existing data)
|
||||
success = fs::rename(temp, local_path, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
// Remove temporary directory manually on failure (removed automatically on success)
|
||||
auto old_error = fs::g_tls_error;
|
||||
fs::remove_all(temp);
|
||||
fs::g_tls_error = old_error;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool TRPLoader::LoadHeader(bool show)
|
||||
|
Loading…
x
Reference in New Issue
Block a user