From 41e15539f95caf255481bd182e9f3db6e31afb29 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 18 Jul 2024 17:28:05 +1000 Subject: [PATCH] FileSystem: Add Error parameter to more functions --- src/common/file_system.cpp | 143 ++++++++++++++++++++++++++++--------- src/common/file_system.h | 6 +- 2 files changed, 112 insertions(+), 37 deletions(-) diff --git a/src/common/file_system.cpp b/src/common/file_system.cpp index ecd7e138a..88b0a89bf 100644 --- a/src/common/file_system.cpp +++ b/src/common/file_system.cpp @@ -1107,20 +1107,35 @@ s64 FileSystem::FTell64(std::FILE* fp) #endif } -s64 FileSystem::FSize64(std::FILE* fp) +s64 FileSystem::FSize64(std::FILE* fp, Error* error) { const s64 pos = FTell64(fp); - if (pos >= 0) + if (pos < 0) [[unlikely]] { - if (FSeek64(fp, 0, SEEK_END) == 0) - { - const s64 size = FTell64(fp); - if (FSeek64(fp, pos, SEEK_SET) == 0) - return size; - } + Error::SetErrno(error, "FTell64() failed: ", errno); + return -1; } - return -1; + if (FSeek64(fp, 0, SEEK_END) != 0) [[unlikely]] + { + Error::SetErrno(error, "FSeek64() to end failed: ", errno); + return -1; + } + + const s64 size = FTell64(fp); + if (size < 0) [[unlikely]] + { + Error::SetErrno(error, "FTell64() failed: ", errno); + return -1; + } + + if (FSeek64(fp, pos, SEEK_SET) != 0) + { + Error::SetErrno(error, "FSeek64() to original position failed: ", errno); + return -1; + } + + return size; } bool FileSystem::FTruncate64(std::FILE* fp, s64 size, Error* error) @@ -1173,52 +1188,112 @@ s64 FileSystem::GetPathFileSize(const char* Path) std::optional> FileSystem::ReadBinaryFile(const char* filename, Error* error) { + std::optional> ret; + ManagedCFilePtr fp = OpenManagedCFile(filename, "rb", error); if (!fp) - return std::nullopt; + return ret; - return ReadBinaryFile(fp.get()); + ret = ReadBinaryFile(fp.get(), error); + return ret; } -std::optional> FileSystem::ReadBinaryFile(std::FILE* fp) +std::optional> FileSystem::ReadBinaryFile(std::FILE* fp, Error* error) { - std::fseek(fp, 0, SEEK_END); - const long size = std::ftell(fp); - std::fseek(fp, 0, SEEK_SET); - if (size < 0) - return std::nullopt; + std::optional> ret; - std::vector res(static_cast(size)); - if (size > 0 && std::fread(res.data(), 1u, static_cast(size), fp) != static_cast(size)) - return std::nullopt; + if (FSeek64(fp, 0, SEEK_END) != 0) [[unlikely]] + { + Error::SetErrno(error, "FSeek64() to end failed: ", errno); + return ret; + } - return res; + const s64 size = FTell64(fp); + if (size < 0) [[unlikely]] + { + Error::SetErrno(error, "FTell64() for length failed: ", errno); + return ret; + } + + if constexpr (sizeof(s64) != sizeof(size_t)) + { + if (size > static_cast(std::numeric_limits::max())) [[unlikely]] + { + Error::SetStringFmt(error, "File size of {} is too large to read on this platform.", size); + return ret; + } + } + + if (FSeek64(fp, 0, SEEK_SET) != 0) [[unlikely]] + { + Error::SetErrno(error, "FSeek64() to start failed: ", errno); + return ret; + } + + ret = std::vector(static_cast(size)); + if (size > 0 && std::fread(ret->data(), 1u, static_cast(size), fp) != static_cast(size)) [[unlikely]] + { + Error::SetErrno(error, "fread() failed: ", errno); + ret.reset(); + } + + return ret; } std::optional FileSystem::ReadFileToString(const char* filename, Error* error) { + std::optional ret; + ManagedCFilePtr fp = OpenManagedCFile(filename, "rb", error); if (!fp) - return std::nullopt; + return ret; - return ReadFileToString(fp.get()); + ret = ReadFileToString(fp.get()); + return ret; } -std::optional FileSystem::ReadFileToString(std::FILE* fp) +std::optional FileSystem::ReadFileToString(std::FILE* fp, Error* error) { - std::fseek(fp, 0, SEEK_END); - const long size = std::ftell(fp); - std::fseek(fp, 0, SEEK_SET); - if (size < 0) - return std::nullopt; + std::optional ret; - std::string res; - res.resize(static_cast(size)); + if (FSeek64(fp, 0, SEEK_END) != 0) [[unlikely]] + { + Error::SetErrno(error, "FSeek64() to end failed: ", errno); + return ret; + } + + const s64 size = FTell64(fp); + if (size < 0) [[unlikely]] + { + Error::SetErrno(error, "FTell64() for length failed: ", errno); + return ret; + } + + if constexpr (sizeof(s64) != sizeof(size_t)) + { + if (size > static_cast(std::numeric_limits::max())) [[unlikely]] + { + Error::SetStringFmt(error, "File size of {} is too large to read on this platform.", size); + return ret; + } + } + + if (FSeek64(fp, 0, SEEK_SET) != 0) [[unlikely]] + { + Error::SetErrno(error, "FSeek64() to start failed: ", errno); + return ret; + } + + ret = std::string(); + ret->resize(static_cast(size)); // NOTE - assumes mode 'rb', for example, this will fail over missing Windows carriage return bytes - if (size > 0 && std::fread(res.data(), 1u, static_cast(size), fp) != static_cast(size)) - return std::nullopt; + if (size > 0 && std::fread(ret->data(), 1u, static_cast(size), fp) != static_cast(size)) + { + Error::SetErrno(error, "fread() failed: ", errno); + ret.reset(); + } - return res; + return ret; } bool FileSystem::WriteBinaryFile(const char* filename, const void* data, size_t data_length, Error* error) diff --git a/src/common/file_system.h b/src/common/file_system.h index 971c285db..d85bcd406 100644 --- a/src/common/file_system.h +++ b/src/common/file_system.h @@ -108,7 +108,7 @@ ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr); int FSeek64(std::FILE* fp, s64 offset, int whence); s64 FTell64(std::FILE* fp); -s64 FSize64(std::FILE* fp); +s64 FSize64(std::FILE* fp, 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); @@ -143,9 +143,9 @@ private: #endif std::optional> ReadBinaryFile(const char* filename, Error* error = nullptr); -std::optional> ReadBinaryFile(std::FILE* fp); +std::optional> ReadBinaryFile(std::FILE* fp, Error* error = nullptr); std::optional ReadFileToString(const char* filename, Error* error = nullptr); -std::optional ReadFileToString(std::FILE* fp); +std::optional ReadFileToString(std::FILE* fp, Error* error = nullptr); bool WriteBinaryFile(const char* filename, const void* data, size_t data_length, Error* error = nullptr); bool WriteStringToFile(const char* filename, std::string_view sv, Error* error = nullptr);