FileSystem: Add span overload for WriteBinaryFile()

And normalize filename -> path parameter names.
This commit is contained in:
Stenzek 2024-11-27 17:19:49 +10:00
parent b97788a35a
commit 1434507b41
No known key found for this signature in database
2 changed files with 102 additions and 90 deletions

View File

@ -608,14 +608,14 @@ std::string Path::ReplaceExtension(std::string_view path, std::string_view new_e
return ret; return ret;
} }
static std::string_view::size_type GetLastSeperatorPosition(std::string_view filename, bool include_separator) static std::string_view::size_type GetLastSeperatorPosition(std::string_view path, bool include_separator)
{ {
std::string_view::size_type last_separator = filename.rfind('/'); std::string_view::size_type last_separator = path.rfind('/');
if (include_separator && last_separator != std::string_view::npos) if (include_separator && last_separator != std::string_view::npos)
last_separator++; last_separator++;
#if defined(_WIN32) #if defined(_WIN32)
std::string_view::size_type other_last_separator = filename.rfind('\\'); std::string_view::size_type other_last_separator = path.rfind('\\');
if (other_last_separator != std::string_view::npos) if (other_last_separator != std::string_view::npos)
{ {
if (include_separator) if (include_separator)
@ -845,13 +845,13 @@ std::vector<std::string> FileSystem::GetRootDirectoryList()
return results; return results;
} }
std::string Path::BuildRelativePath(std::string_view filename, std::string_view new_filename) std::string Path::BuildRelativePath(std::string_view path, std::string_view new_filename)
{ {
std::string new_string; std::string new_string;
std::string_view::size_type pos = GetLastSeperatorPosition(filename, true); std::string_view::size_type pos = GetLastSeperatorPosition(path, true);
if (pos != std::string_view::npos) if (pos != std::string_view::npos)
new_string.assign(filename, 0, pos); new_string.assign(path, 0, pos);
new_string.append(new_filename); new_string.append(new_filename);
return new_string; return new_string;
} }
@ -873,10 +873,10 @@ std::string Path::Combine(std::string_view base, std::string_view next)
return ret; return ret;
} }
std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode, Error* error) std::FILE* FileSystem::OpenCFile(const char* path, const char* mode, Error* error)
{ {
#ifdef _WIN32 #ifdef _WIN32
const std::wstring wfilename = GetWin32Path(filename); const std::wstring wfilename = GetWin32Path(path);
const std::wstring wmode = StringUtil::UTF8StringToWideString(mode); const std::wstring wmode = StringUtil::UTF8StringToWideString(mode);
if (!wfilename.empty() && !wmode.empty()) if (!wfilename.empty() && !wmode.empty())
{ {
@ -892,7 +892,7 @@ std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode, Error*
} }
std::FILE* fp; std::FILE* fp;
const errno_t err = fopen_s(&fp, filename, mode); const errno_t err = fopen_s(&fp, path, mode);
if (err != 0) if (err != 0)
{ {
Error::SetErrno(error, err); Error::SetErrno(error, err);
@ -901,24 +901,24 @@ std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode, Error*
return fp; return fp;
#else #else
std::FILE* fp = std::fopen(filename, mode); std::FILE* fp = std::fopen(path, mode);
if (!fp) if (!fp)
Error::SetErrno(error, errno); Error::SetErrno(error, errno);
return fp; return fp;
#endif #endif
} }
std::FILE* FileSystem::OpenExistingOrCreateCFile(const char* filename, s32 retry_ms, Error* error /*= nullptr*/) std::FILE* FileSystem::OpenExistingOrCreateCFile(const char* path, s32 retry_ms, Error* error /*= nullptr*/)
{ {
#ifdef _WIN32 #ifdef _WIN32
const std::wstring wfilename = GetWin32Path(filename); const std::wstring wpath = GetWin32Path(path);
if (wfilename.empty()) if (wpath.empty())
{ {
Error::SetStringView(error, "Invalid path."); Error::SetStringView(error, "Invalid path.");
return nullptr; return nullptr;
} }
HANDLE file = CreateFileW(wfilename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, NULL); HANDLE file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, NULL);
// if there's a sharing violation, keep retrying // if there's a sharing violation, keep retrying
if (file == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION && retry_ms >= 0) if (file == INVALID_HANDLE_VALUE && GetLastError() == ERROR_SHARING_VIOLATION && retry_ms >= 0)
@ -927,7 +927,7 @@ std::FILE* FileSystem::OpenExistingOrCreateCFile(const char* filename, s32 retry
while (retry_ms == 0 || timer.GetTimeMilliseconds() <= retry_ms) while (retry_ms == 0 || timer.GetTimeMilliseconds() <= retry_ms)
{ {
Sleep(1); Sleep(1);
file = CreateFileW(wfilename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, NULL); file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, NULL);
if (file != INVALID_HANDLE_VALUE || GetLastError() != ERROR_SHARING_VIOLATION) if (file != INVALID_HANDLE_VALUE || GetLastError() != ERROR_SHARING_VIOLATION)
break; break;
} }
@ -936,11 +936,11 @@ std::FILE* FileSystem::OpenExistingOrCreateCFile(const char* filename, s32 retry
if (file == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) if (file == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
{ {
// try creating it // try creating it
file = CreateFileW(wfilename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_NEW, 0, NULL); file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_NEW, 0, NULL);
if (file == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS) if (file == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS)
{ {
// someone else beat us in the race, try again with existing. // someone else beat us in the race, try again with existing.
file = CreateFileW(wfilename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, NULL); file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, NULL);
} }
} }
@ -970,7 +970,7 @@ std::FILE* FileSystem::OpenExistingOrCreateCFile(const char* filename, s32 retry
return cfile; return cfile;
#else #else
std::FILE* fp = std::fopen(filename, "r+b"); std::FILE* fp = std::fopen(path, "r+b");
if (fp) if (fp)
return fp; return fp;
@ -982,13 +982,13 @@ std::FILE* FileSystem::OpenExistingOrCreateCFile(const char* filename, s32 retry
} }
// try again, but create the file. mode "x" exists on all platforms. // try again, but create the file. mode "x" exists on all platforms.
fp = std::fopen(filename, "w+bx"); fp = std::fopen(path, "w+bx");
if (fp) if (fp)
return fp; return fp;
// if it already exists, someone else beat us in the race. try again with existing. // if it already exists, someone else beat us in the race. try again with existing.
if (errno == EEXIST) if (errno == EEXIST)
fp = std::fopen(filename, "r+b"); fp = std::fopen(path, "r+b");
if (!fp) if (!fp)
{ {
Error::SetErrno(error, errno); Error::SetErrno(error, errno);
@ -999,28 +999,28 @@ std::FILE* FileSystem::OpenExistingOrCreateCFile(const char* filename, s32 retry
#endif #endif
} }
int FileSystem::OpenFDFile(const char* filename, int flags, int mode, Error* error) int FileSystem::OpenFDFile(const char* path, int flags, int mode, Error* error)
{ {
#ifdef _WIN32 #ifdef _WIN32
const std::wstring wfilename(GetWin32Path(filename)); const std::wstring wpath = GetWin32Path(path);
if (!wfilename.empty()) if (!wpath.empty())
return _wopen(wfilename.c_str(), flags, mode); return _wopen(wpath.c_str(), flags, mode);
return -1; return -1;
#else #else
const int fd = open(filename, flags, mode); const int fd = open(path, flags, mode);
if (fd < 0) if (fd < 0)
Error::SetErrno(error, errno); Error::SetErrno(error, errno);
return fd; return fd;
#endif #endif
} }
std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error) std::FILE* FileSystem::OpenSharedCFile(const char* path, const char* mode, FileShareMode share_mode, Error* error)
{ {
#ifdef _WIN32 #ifdef _WIN32
const std::wstring wfilename = GetWin32Path(filename); const std::wstring wpath = GetWin32Path(path);
const std::wstring wmode = StringUtil::UTF8StringToWideString(mode); const std::wstring wmode = StringUtil::UTF8StringToWideString(mode);
if (wfilename.empty() || wmode.empty()) if (wpath.empty() || wmode.empty())
return nullptr; return nullptr;
int share_flags = 0; int share_flags = 0;
@ -1041,14 +1041,14 @@ std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, F
break; break;
} }
std::FILE* fp = _wfsopen(wfilename.c_str(), wmode.c_str(), share_flags); std::FILE* fp = _wfsopen(wpath.c_str(), wmode.c_str(), share_flags);
if (fp) if (fp)
return fp; return fp;
Error::SetErrno(error, errno); Error::SetErrno(error, errno);
return nullptr; return nullptr;
#else #else
std::FILE* fp = std::fopen(filename, mode); std::FILE* fp = std::fopen(path, mode);
if (!fp) if (!fp)
Error::SetErrno(error, errno); Error::SetErrno(error, errno);
return fp; return fp;
@ -1165,8 +1165,8 @@ std::string Path::CreateFileURL(std::string_view path)
return ret; return ret;
} }
FileSystem::AtomicRenamedFileDeleter::AtomicRenamedFileDeleter(std::string temp_filename, std::string final_filename) FileSystem::AtomicRenamedFileDeleter::AtomicRenamedFileDeleter(std::string temp_path, std::string final_path)
: m_temp_filename(std::move(temp_filename)), m_final_filename(std::move(final_filename)) : m_temp_path(std::move(temp_path)), m_final_path(std::move(final_path))
{ {
} }
@ -1180,11 +1180,11 @@ void FileSystem::AtomicRenamedFileDeleter::operator()(std::FILE* fp)
Error error; Error error;
// final filename empty => discarded. // final filename empty => discarded.
if (!m_final_filename.empty()) if (!m_final_path.empty())
{ {
if (!commit(fp, &error)) if (!commit(fp, &error))
{ {
ERROR_LOG("Failed to commit temporary file '{}', discarding. Error was {}.", Path::GetFileName(m_temp_filename), ERROR_LOG("Failed to commit temporary file '{}', discarding. Error was {}.", Path::GetFileName(m_temp_path),
error.GetDescription()); error.GetDescription());
} }
@ -1194,8 +1194,8 @@ void FileSystem::AtomicRenamedFileDeleter::operator()(std::FILE* fp)
// we're discarding the file, don't care if it fails. // we're discarding the file, don't care if it fails.
std::fclose(fp); std::fclose(fp);
if (!DeleteFile(m_temp_filename.c_str(), &error)) if (!DeleteFile(m_temp_path.c_str(), &error))
ERROR_LOG("Failed to delete temporary file '{}': {}", Path::GetFileName(m_temp_filename), error.GetDescription()); ERROR_LOG("Failed to delete temporary file '{}': {}", Path::GetFileName(m_temp_path), error.GetDescription());
} }
bool FileSystem::AtomicRenamedFileDeleter::commit(std::FILE* fp, Error* error) bool FileSystem::AtomicRenamedFileDeleter::commit(std::FILE* fp, Error* error)
@ -1209,38 +1209,38 @@ bool FileSystem::AtomicRenamedFileDeleter::commit(std::FILE* fp, Error* error)
if (std::fclose(fp) != 0) if (std::fclose(fp) != 0)
{ {
Error::SetErrno(error, "fclose() failed: ", errno); Error::SetErrno(error, "fclose() failed: ", errno);
m_final_filename.clear(); m_final_path.clear();
} }
// Should not have been discarded. // Should not have been discarded.
if (!m_final_filename.empty()) if (!m_final_path.empty())
{ {
return RenamePath(m_temp_filename.c_str(), m_final_filename.c_str(), error); return RenamePath(m_temp_path.c_str(), m_final_path.c_str(), error);
} }
else else
{ {
Error::SetStringView(error, "File has already been discarded."); Error::SetStringView(error, "File has already been discarded.");
return DeleteFile(m_temp_filename.c_str(), error); return DeleteFile(m_temp_path.c_str(), error);
} }
} }
void FileSystem::AtomicRenamedFileDeleter::discard() void FileSystem::AtomicRenamedFileDeleter::discard()
{ {
m_final_filename = {}; m_final_path = {};
} }
FileSystem::AtomicRenamedFile FileSystem::CreateAtomicRenamedFile(std::string filename, Error* error /*= nullptr*/) FileSystem::AtomicRenamedFile FileSystem::CreateAtomicRenamedFile(std::string path, Error* error /*= nullptr*/)
{ {
std::string temp_filename; std::string temp_path;
std::FILE* fp = nullptr; std::FILE* fp = nullptr;
if (!filename.empty()) if (!path.empty())
{ {
// this is disgusting, but we need null termination, and std::string::data() does not guarantee it. // this is disgusting, but we need null termination, and std::string::data() does not guarantee it.
const size_t filename_length = filename.length(); const size_t path_length = path.length();
const size_t name_buf_size = filename_length + 8; const size_t name_buf_size = path_length + 8;
std::unique_ptr<char[]> name_buf = std::make_unique<char[]>(name_buf_size); std::unique_ptr<char[]> name_buf = std::make_unique<char[]>(name_buf_size);
std::memcpy(name_buf.get(), filename.c_str(), filename_length); std::memcpy(name_buf.get(), path.c_str(), path_length);
StringUtil::Strlcpy(name_buf.get() + filename_length, ".XXXXXX", name_buf_size); StringUtil::Strlcpy(name_buf.get() + path_length, ".XXXXXX", name_buf_size);
#ifdef _WIN32 #ifdef _WIN32
const errno_t err = _mktemp_s(name_buf.get(), name_buf_size); const errno_t err = _mktemp_s(name_buf.get(), name_buf_size);
@ -1267,18 +1267,18 @@ FileSystem::AtomicRenamedFile FileSystem::CreateAtomicRenamedFile(std::string fi
#endif #endif
if (fp) if (fp)
temp_filename.assign(name_buf.get(), name_buf_size - 1); temp_path.assign(name_buf.get(), name_buf_size - 1);
else else
filename.clear(); path.clear();
} }
return AtomicRenamedFile(fp, AtomicRenamedFileDeleter(std::move(temp_filename), std::move(filename))); return AtomicRenamedFile(fp, AtomicRenamedFileDeleter(std::move(temp_path), std::move(path)));
} }
bool FileSystem::WriteAtomicRenamedFile(std::string filename, const void* data, size_t data_length, bool FileSystem::WriteAtomicRenamedFile(std::string path, const void* data, size_t data_length,
Error* error /*= nullptr*/) Error* error /*= nullptr*/)
{ {
AtomicRenamedFile fp = CreateAtomicRenamedFile(std::move(filename), error); AtomicRenamedFile fp = CreateAtomicRenamedFile(std::move(path), error);
if (!fp) if (!fp)
return false; return false;
@ -1292,6 +1292,11 @@ bool FileSystem::WriteAtomicRenamedFile(std::string filename, const void* data,
return true; return true;
} }
bool FileSystem::WriteAtomicRenamedFile(std::string path, const std::span<const u8> data, Error* error /* = nullptr */)
{
return WriteAtomicRenamedFile(std::move(path), data.empty() ? nullptr : data.data(), data.size(), error);
}
void FileSystem::DiscardAtomicRenamedFile(AtomicRenamedFile& file) void FileSystem::DiscardAtomicRenamedFile(AtomicRenamedFile& file)
{ {
file.get_deleter().discard(); file.get_deleter().discard();
@ -1306,21 +1311,20 @@ bool FileSystem::CommitAtomicRenamedFile(AtomicRenamedFile& file, Error* error)
return false; return false;
} }
FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, const char* mode, Error* error) FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* path, const char* mode, Error* error)
{ {
return ManagedCFilePtr(OpenCFile(filename, mode, error)); return ManagedCFilePtr(OpenCFile(path, mode, error));
} }
FileSystem::ManagedCFilePtr FileSystem::OpenExistingOrCreateManagedCFile(const char* filename, s32 retry_ms, FileSystem::ManagedCFilePtr FileSystem::OpenExistingOrCreateManagedCFile(const char* path, s32 retry_ms, Error* error)
Error* error)
{ {
return ManagedCFilePtr(OpenExistingOrCreateCFile(filename, retry_ms, error)); return ManagedCFilePtr(OpenExistingOrCreateCFile(path, retry_ms, error));
} }
FileSystem::ManagedCFilePtr FileSystem::OpenManagedSharedCFile(const char* filename, const char* mode, FileSystem::ManagedCFilePtr FileSystem::OpenManagedSharedCFile(const char* path, const char* mode,
FileShareMode share_mode, Error* error) FileShareMode share_mode, Error* error)
{ {
return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode, error)); return ManagedCFilePtr(OpenSharedCFile(path, mode, share_mode, error));
} }
int FileSystem::FSeek64(std::FILE* fp, s64 offset, int whence) int FileSystem::FSeek64(std::FILE* fp, s64 offset, int whence)
@ -1443,20 +1447,20 @@ bool FileSystem::FTruncate64(std::FILE* fp, s64 size, Error* error)
#endif #endif
} }
s64 FileSystem::GetPathFileSize(const char* Path) s64 FileSystem::GetPathFileSize(const char* path)
{ {
FILESYSTEM_STAT_DATA sd; FILESYSTEM_STAT_DATA sd;
if (!StatFile(Path, &sd)) if (!StatFile(path, &sd))
return -1; return -1;
return sd.Size; return sd.Size;
} }
std::optional<DynamicHeapArray<u8>> FileSystem::ReadBinaryFile(const char* filename, Error* error) std::optional<DynamicHeapArray<u8>> FileSystem::ReadBinaryFile(const char* path, Error* error)
{ {
std::optional<DynamicHeapArray<u8>> ret; std::optional<DynamicHeapArray<u8>> ret;
ManagedCFilePtr fp = OpenManagedCFile(filename, "rb", error); ManagedCFilePtr fp = OpenManagedCFile(path, "rb", error);
if (!fp) if (!fp)
return ret; return ret;
@ -1506,11 +1510,11 @@ std::optional<DynamicHeapArray<u8>> FileSystem::ReadBinaryFile(std::FILE* fp, Er
return ret; return ret;
} }
std::optional<std::string> FileSystem::ReadFileToString(const char* filename, Error* error) std::optional<std::string> FileSystem::ReadFileToString(const char* path, Error* error)
{ {
std::optional<std::string> ret; std::optional<std::string> ret;
ManagedCFilePtr fp = OpenManagedCFile(filename, "rb", error); ManagedCFilePtr fp = OpenManagedCFile(path, "rb", error);
if (!fp) if (!fp)
return ret; return ret;
@ -1562,9 +1566,9 @@ std::optional<std::string> FileSystem::ReadFileToString(std::FILE* fp, Error* er
return ret; return ret;
} }
bool FileSystem::WriteBinaryFile(const char* filename, const void* data, size_t data_length, Error* error) bool FileSystem::WriteBinaryFile(const char* path, const void* data, size_t data_length, Error* error)
{ {
ManagedCFilePtr fp = OpenManagedCFile(filename, "wb", error); ManagedCFilePtr fp = OpenManagedCFile(path, "wb", error);
if (!fp) if (!fp)
return false; return false;
@ -1577,9 +1581,14 @@ bool FileSystem::WriteBinaryFile(const char* filename, const void* data, size_t
return true; return true;
} }
bool FileSystem::WriteStringToFile(const char* filename, std::string_view sv, Error* error) bool FileSystem::WriteBinaryFile(const char* path, const std::span<const u8> data, Error* error /*= nullptr*/)
{ {
ManagedCFilePtr fp = OpenManagedCFile(filename, "wb", error); return WriteBinaryFile(path, data.empty() ? nullptr : data.data(), data.size(), error);
}
bool FileSystem::WriteStringToFile(const char* path, std::string_view sv, Error* error)
{
ManagedCFilePtr fp = OpenManagedCFile(path, "wb", error);
if (!fp) if (!fp)
return false; return false;
@ -2636,13 +2645,13 @@ bool FileSystem::DeleteDirectory(const char* path)
std::string FileSystem::GetProgramPath() std::string FileSystem::GetProgramPath()
{ {
#if defined(__linux__) #if defined(__linux__)
static const char* exeFileName = "/proc/self/exe"; static const char* exe_path = "/proc/self/exe";
int curSize = PATH_MAX; int curSize = PATH_MAX;
char* buffer = static_cast<char*>(std::realloc(nullptr, curSize)); char* buffer = static_cast<char*>(std::realloc(nullptr, curSize));
for (;;) for (;;)
{ {
int len = readlink(exeFileName, buffer, curSize); int len = readlink(exe_path, buffer, curSize);
if (len < 0) if (len < 0)
{ {
std::free(buffer); std::free(buffer);

View File

@ -10,6 +10,7 @@
#include <ctime> #include <ctime>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <span>
#include <string> #include <string>
#include <sys/stat.h> #include <sys/stat.h>
#include <vector> #include <vector>
@ -67,8 +68,8 @@ bool FindFiles(const char* path, const char* pattern, u32 flags, FindResultsArra
/// Stat file /// Stat file
bool StatFile(const char* path, struct stat* st); bool StatFile(const char* path, struct stat* st);
bool StatFile(std::FILE* fp, struct stat* st); bool StatFile(std::FILE* fp, struct stat* st);
bool StatFile(const char* path, FILESYSTEM_STAT_DATA* pStatData); bool StatFile(const char* path, FILESYSTEM_STAT_DATA* sd);
bool StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* pStatData); bool StatFile(std::FILE* fp, FILESYSTEM_STAT_DATA* sd);
s64 GetPathFileSize(const char* path); s64 GetPathFileSize(const char* path);
/// File exists? /// File exists?
@ -99,14 +100,14 @@ struct FileDeleter
/// open files /// open files
using ManagedCFilePtr = std::unique_ptr<std::FILE, FileDeleter>; using ManagedCFilePtr = std::unique_ptr<std::FILE, FileDeleter>;
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* error = nullptr); ManagedCFilePtr OpenManagedCFile(const char* path, const char* mode, Error* error = nullptr);
std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr); std::FILE* OpenCFile(const char* path, const char* mode, Error* error = nullptr);
/// Atomically opens a file in read/write mode, and if the file does not exist, creates it. /// Atomically opens a file in read/write mode, and if the file does not exist, creates it.
/// On Windows, if retry_ms is positive, this function will retry opening the file for this /// On Windows, if retry_ms is positive, this function will retry opening the file for this
/// number of milliseconds. NOTE: The file is opened in binary mode. /// number of milliseconds. NOTE: The file is opened in binary mode.
std::FILE* OpenExistingOrCreateCFile(const char* filename, s32 retry_ms = -1, Error* error = nullptr); std::FILE* OpenExistingOrCreateCFile(const char* path, s32 retry_ms = -1, Error* error = nullptr);
ManagedCFilePtr OpenExistingOrCreateManagedCFile(const char* filename, s32 retry_ms = -1, Error* error = nullptr); ManagedCFilePtr OpenExistingOrCreateManagedCFile(const char* path, s32 retry_ms = -1, Error* error = nullptr);
int FSeek64(std::FILE* fp, s64 offset, int whence); int FSeek64(std::FILE* fp, s64 offset, int whence);
bool FSeek64(std::FILE* fp, s64 offset, int whence, Error* error); bool FSeek64(std::FILE* fp, s64 offset, int whence, Error* error);
@ -114,7 +115,7 @@ s64 FTell64(std::FILE* fp);
s64 FSize64(std::FILE* fp, Error* error = nullptr); s64 FSize64(std::FILE* fp, Error* error = nullptr);
bool FTruncate64(std::FILE* fp, s64 size, Error* error = nullptr); bool FTruncate64(std::FILE* fp, s64 size, Error* error = nullptr);
int OpenFDFile(const char* filename, int flags, int mode, Error* error = nullptr); int OpenFDFile(const char* path, int flags, int mode, Error* error = nullptr);
/// Sharing modes for OpenSharedCFile(). /// Sharing modes for OpenSharedCFile().
enum class FileShareMode enum class FileShareMode
@ -127,15 +128,15 @@ enum class FileShareMode
/// Opens a file in shareable mode (where other processes can access it concurrently). /// Opens a file in shareable mode (where other processes can access it concurrently).
/// Only has an effect on Windows systems. /// Only has an effect on Windows systems.
ManagedCFilePtr OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, ManagedCFilePtr OpenManagedSharedCFile(const char* path, const char* mode, FileShareMode share_mode,
Error* error = nullptr); Error* error = nullptr);
std::FILE* OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error = nullptr); std::FILE* OpenSharedCFile(const char* path, const char* mode, FileShareMode share_mode, Error* error = nullptr);
/// Atomically-updated file creation. /// Atomically-updated file creation.
class AtomicRenamedFileDeleter class AtomicRenamedFileDeleter
{ {
public: public:
AtomicRenamedFileDeleter(std::string temp_filename, std::string final_filename); AtomicRenamedFileDeleter(std::string temp_path, std::string final_path);
~AtomicRenamedFileDeleter(); ~AtomicRenamedFileDeleter();
void operator()(std::FILE* fp); void operator()(std::FILE* fp);
@ -143,12 +144,13 @@ public:
void discard(); void discard();
private: private:
std::string m_temp_filename; std::string m_temp_path;
std::string m_final_filename; std::string m_final_path;
}; };
using AtomicRenamedFile = std::unique_ptr<std::FILE, AtomicRenamedFileDeleter>; using AtomicRenamedFile = std::unique_ptr<std::FILE, AtomicRenamedFileDeleter>;
AtomicRenamedFile CreateAtomicRenamedFile(std::string filename, Error* error = nullptr); AtomicRenamedFile CreateAtomicRenamedFile(std::string path, Error* error = nullptr);
bool WriteAtomicRenamedFile(std::string filename, const void* data, size_t data_length, Error* error = nullptr); bool WriteAtomicRenamedFile(std::string path, const void* data, size_t data_length, Error* error = nullptr);
bool WriteAtomicRenamedFile(std::string path, const std::span<const u8> data, Error* error = nullptr);
bool CommitAtomicRenamedFile(AtomicRenamedFile& file, Error* error); bool CommitAtomicRenamedFile(AtomicRenamedFile& file, Error* error);
void DiscardAtomicRenamedFile(AtomicRenamedFile& file); void DiscardAtomicRenamedFile(AtomicRenamedFile& file);
@ -166,12 +168,13 @@ private:
}; };
#endif #endif
std::optional<DynamicHeapArray<u8>> ReadBinaryFile(const char* filename, Error* error = nullptr); std::optional<DynamicHeapArray<u8>> ReadBinaryFile(const char* path, Error* error = nullptr);
std::optional<DynamicHeapArray<u8>> ReadBinaryFile(std::FILE* fp, Error* error = nullptr); std::optional<DynamicHeapArray<u8>> ReadBinaryFile(std::FILE* fp, Error* error = nullptr);
std::optional<std::string> ReadFileToString(const char* filename, Error* error = nullptr); std::optional<std::string> ReadFileToString(const char* path, Error* error = nullptr);
std::optional<std::string> ReadFileToString(std::FILE* fp, Error* error = nullptr); std::optional<std::string> ReadFileToString(std::FILE* fp, Error* error = nullptr);
bool WriteBinaryFile(const char* filename, const void* data, size_t data_length, Error* error = nullptr); bool WriteBinaryFile(const char* path, const void* data, size_t data_length, Error* error = nullptr);
bool WriteStringToFile(const char* filename, std::string_view sv, Error* error = nullptr); bool WriteBinaryFile(const char* path, const std::span<const u8> data, Error* error = nullptr);
bool WriteStringToFile(const char* path, std::string_view sv, Error* error = nullptr);
/// creates a directory in the local filesystem /// creates a directory in the local filesystem
/// if the directory already exists, the return value will be true. /// if the directory already exists, the return value will be true.