mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-02-20 07:13:49 -07:00
Common/FileUtil: Add CreateTempFileForAtomicWrite function.
This commit is contained in:
parent
267e081592
commit
c84f78f058
@ -25,6 +25,7 @@
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/DirectIOFile.h"
|
||||
#ifdef __APPLE__
|
||||
#include "Common/DynamicLibrary.h"
|
||||
#endif
|
||||
@ -668,13 +669,42 @@ std::string CreateTempDir()
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string GetTempFilenameForAtomicWrite(std::string path)
|
||||
static auto TryToGetAbsolutePath(std::string path)
|
||||
{
|
||||
std::error_code error;
|
||||
auto absolute_path = fs::absolute(StringToPath(path), error);
|
||||
if (!error)
|
||||
path = PathToString(absolute_path);
|
||||
return std::move(path) + ".xxx";
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string GetTempFilenameForAtomicWrite(std::string path)
|
||||
{
|
||||
return TryToGetAbsolutePath(std::move(path)) + ".xxx";
|
||||
}
|
||||
|
||||
std::string CreateTempFileForAtomicWrite(std::string path)
|
||||
{
|
||||
path = TryToGetAbsolutePath(std::move(path));
|
||||
while (true)
|
||||
{
|
||||
DirectIOFile file;
|
||||
|
||||
// e.g. "/dir/file.txt" -> "/dir/file.txt.189234789.tmp"
|
||||
const auto timestamp = Clock::now().time_since_epoch().count();
|
||||
std::string tmp_path = fmt::format("{}.{}.tmp", path, timestamp);
|
||||
|
||||
const auto open_result = file.Open(tmp_path, AccessMode::Write, OpenMode::Create);
|
||||
if (open_result.Succeeded())
|
||||
return tmp_path;
|
||||
|
||||
// In the very unlikely case that the file already exists, we will try again.
|
||||
if (open_result.Error() == File::OpenError::AlreadyExists)
|
||||
continue;
|
||||
|
||||
// Failure.
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
@ -223,6 +223,10 @@ std::string CreateTempDir();
|
||||
// Get a filename that can hopefully be atomically renamed to the given path.
|
||||
std::string GetTempFilenameForAtomicWrite(std::string path);
|
||||
|
||||
// Creates and returns the path to a newly created temporary file next to the given path.
|
||||
// Returns an empty string on error, generally caused by lack of write permissions.
|
||||
std::string CreateTempFileForAtomicWrite(std::string path);
|
||||
|
||||
// Gets a set user directory path
|
||||
// Don't call prior to setting the base user directory
|
||||
const std::string& GetUserPath(unsigned int dir_index);
|
||||
|
||||
@ -154,6 +154,17 @@ TEST_F(FileUtilTest, CreateFullPath)
|
||||
EXPECT_TRUE(File::IsFile(p3file));
|
||||
}
|
||||
|
||||
TEST_F(FileUtilTest, CreateTempFileForAtomicWrite)
|
||||
{
|
||||
EXPECT_TRUE(File::Exists(File::CreateTempFileForAtomicWrite(m_file_path)));
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_FALSE(File::Exists(File::CreateTempFileForAtomicWrite("C:/con/cant_write_here.txt")));
|
||||
#else
|
||||
EXPECT_FALSE(File::Exists(File::CreateTempFileForAtomicWrite("/dev/null/cant_write_here.txt")));
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(FileUtilTest, DirectIOFile)
|
||||
{
|
||||
static constexpr std::array<u8, 3> u8_test_data = {42, 7, 99};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user