summaryrefslogtreecommitdiffstats
path: root/src/common/fs
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/fs')
-rw-r--r--src/common/fs/file.cpp33
-rw-r--r--src/common/fs/file.h21
-rw-r--r--src/common/fs/fs.cpp5
-rw-r--r--src/common/fs/fs.h30
-rw-r--r--src/common/fs/fs_util.cpp4
-rw-r--r--src/common/fs/fs_util.h11
6 files changed, 79 insertions, 25 deletions
diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp
index 710e88b39..274f57659 100644
--- a/src/common/fs/file.cpp
+++ b/src/common/fs/file.cpp
@@ -172,7 +172,7 @@ std::string ReadStringFromFile(const std::filesystem::path& path, FileType type)
size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string) {
- if (!IsFile(path)) {
+ if (Exists(path) && !IsFile(path)) {
return 0;
}
@@ -183,7 +183,7 @@ size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
size_t AppendStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string) {
- if (!IsFile(path)) {
+ if (Exists(path) && !IsFile(path)) {
return 0;
}
@@ -306,9 +306,9 @@ bool IOFile::Flush() const {
errno = 0;
#ifdef _WIN32
- const auto flush_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0;
+ const auto flush_result = std::fflush(file) == 0;
#else
- const auto flush_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0;
+ const auto flush_result = std::fflush(file) == 0;
#endif
if (!flush_result) {
@@ -320,6 +320,28 @@ bool IOFile::Flush() const {
return flush_result;
}
+bool IOFile::Commit() const {
+ if (!IsOpen()) {
+ return false;
+ }
+
+ errno = 0;
+
+#ifdef _WIN32
+ const auto commit_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0;
+#else
+ const auto commit_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0;
+#endif
+
+ if (!commit_result) {
+ const auto ec = std::error_code{errno, std::generic_category()};
+ LOG_ERROR(Common_Filesystem, "Failed to commit the file at path={}, ec_message={}",
+ PathToUTF8String(file_path), ec.message());
+ }
+
+ return commit_result;
+}
+
bool IOFile::SetSize(u64 size) const {
if (!IsOpen()) {
return false;
@@ -347,6 +369,9 @@ u64 IOFile::GetSize() const {
return 0;
}
+ // Flush any unwritten buffered data into the file prior to retrieving the file size.
+ std::fflush(file);
+
std::error_code ec;
const auto file_size = fs::file_size(file_path, ec);
diff --git a/src/common/fs/file.h b/src/common/fs/file.h
index 0f10b6003..2c4ab4332 100644
--- a/src/common/fs/file.h
+++ b/src/common/fs/file.h
@@ -49,7 +49,7 @@ void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::op
/**
* Reads an entire file at path and returns a string of the contents read from the file.
- * If the filesystem object at path is not a file, this function returns an empty string.
+ * If the filesystem object at path is not a regular file, this function returns an empty string.
*
* @param path Filesystem path
* @param type File type
@@ -72,7 +72,8 @@ template <typename Path>
/**
* Writes a string to a file at path and returns the number of characters successfully written.
* If a file already exists at path, its contents will be erased.
- * If the filesystem object at path is not a file, this function returns 0.
+ * If a file does not exist at path, it creates and opens a new empty file for writing.
+ * If the filesystem object at path exists and is not a regular file, this function returns 0.
*
* @param path Filesystem path
* @param type File type
@@ -95,7 +96,8 @@ template <typename Path>
/**
* Appends a string to a file at path and returns the number of characters successfully written.
- * If the filesystem object at path is not a file, this function returns 0.
+ * If a file does not exist at path, it creates and opens a new empty file for appending.
+ * If the filesystem object at path exists and is not a regular file, this function returns 0.
*
* @param path Filesystem path
* @param type File type
@@ -394,11 +396,20 @@ public:
[[nodiscard]] size_t WriteString(std::span<const char> string) const;
/**
- * Flushes any unwritten buffered data into the file.
+ * Attempts to flush any unwritten buffered data into the file.
*
* @returns True if the flush was successful, false otherwise.
*/
- [[nodiscard]] bool Flush() const;
+ bool Flush() const;
+
+ /**
+ * Attempts to commit the file into the disk.
+ * Note that this is an expensive operation as this forces the operating system to write
+ * the contents of the file associated with the file descriptor into the disk.
+ *
+ * @returns True if the commit was successful, false otherwise.
+ */
+ bool Commit() const;
/**
* Resizes the file to a given size.
diff --git a/src/common/fs/fs.cpp b/src/common/fs/fs.cpp
index d3159e908..9089cad67 100644
--- a/src/common/fs/fs.cpp
+++ b/src/common/fs/fs.cpp
@@ -135,8 +135,9 @@ std::shared_ptr<IOFile> FileOpen(const fs::path& path, FileAccessMode mode, File
return nullptr;
}
- if (!IsFile(path)) {
- LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a file",
+ if (Exists(path) && !IsFile(path)) {
+ LOG_ERROR(Common_Filesystem,
+ "Filesystem object at path={} exists and is not a regular file",
PathToUTF8String(path));
return nullptr;
}
diff --git a/src/common/fs/fs.h b/src/common/fs/fs.h
index f6f256349..183126de3 100644
--- a/src/common/fs/fs.h
+++ b/src/common/fs/fs.h
@@ -48,18 +48,18 @@ template <typename Path>
*
* Failures occur when:
* - Input path is not valid
- * - Filesystem object at path is not a file
+ * - Filesystem object at path is not a regular file
* - Filesystem at path is read only
*
* @param path Filesystem path
*
* @returns True if file removal succeeds or file does not exist, false otherwise.
*/
-[[nodiscard]] bool RemoveFile(const std::filesystem::path& path);
+bool RemoveFile(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
-[[nodiscard]] bool RemoveFile(const Path& path) {
+bool RemoveFile(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return RemoveFile(ToU8String(path));
} else {
@@ -74,7 +74,7 @@ template <typename Path>
* Failures occur when:
* - One or both input path(s) is not valid
* - Filesystem object at old_path does not exist
- * - Filesystem object at old_path is not a file
+ * - Filesystem object at old_path is not a regular file
* - Filesystem object at new_path exists
* - Filesystem at either path is read only
*
@@ -110,8 +110,8 @@ template <typename Path1, typename Path2>
*
* Failures occur when:
* - Input path is not valid
- * - Filesystem object at path is not a file
- * - The file is not opened
+ * - Filesystem object at path exists and is not a regular file
+ * - The file is not open
*
* @param path Filesystem path
* @param mode File access mode
@@ -251,11 +251,11 @@ template <typename Path>
*
* @returns True if directory removal succeeds or directory does not exist, false otherwise.
*/
-[[nodiscard]] bool RemoveDir(const std::filesystem::path& path);
+bool RemoveDir(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
-[[nodiscard]] bool RemoveDir(const Path& path) {
+bool RemoveDir(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return RemoveDir(ToU8String(path));
} else {
@@ -276,11 +276,11 @@ template <typename Path>
*
* @returns True if the directory and all of its contents are removed successfully, false otherwise.
*/
-[[nodiscard]] bool RemoveDirRecursively(const std::filesystem::path& path);
+bool RemoveDirRecursively(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
-[[nodiscard]] bool RemoveDirRecursively(const Path& path) {
+bool RemoveDirRecursively(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return RemoveDirRecursively(ToU8String(path));
} else {
@@ -301,11 +301,11 @@ template <typename Path>
*
* @returns True if all of the directory's contents are removed successfully, false otherwise.
*/
-[[nodiscard]] bool RemoveDirContentsRecursively(const std::filesystem::path& path);
+bool RemoveDirContentsRecursively(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
-[[nodiscard]] bool RemoveDirContentsRecursively(const Path& path) {
+bool RemoveDirContentsRecursively(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return RemoveDirContentsRecursively(ToU8String(path));
} else {
@@ -435,11 +435,13 @@ template <typename Path>
#endif
/**
- * Returns whether a filesystem object at path is a file.
+ * Returns whether a filesystem object at path is a regular file.
+ * A regular file is a file that stores text or binary data.
+ * It is not a directory, symlink, FIFO, socket, block device, or character device.
*
* @param path Filesystem path
*
- * @returns True if a filesystem object at path is a file, false otherwise.
+ * @returns True if a filesystem object at path is a regular file, false otherwise.
*/
[[nodiscard]] bool IsFile(const std::filesystem::path& path);
diff --git a/src/common/fs/fs_util.cpp b/src/common/fs/fs_util.cpp
index 357cf5855..9f8671982 100644
--- a/src/common/fs/fs_util.cpp
+++ b/src/common/fs/fs_util.cpp
@@ -20,6 +20,10 @@ std::string ToUTF8String(std::u8string_view u8_string) {
return std::string{u8_string.begin(), u8_string.end()};
}
+std::string BufferToUTF8String(std::span<const u8> buffer) {
+ return std::string{buffer.begin(), std::ranges::find(buffer, u8{0})};
+}
+
std::string PathToUTF8String(const std::filesystem::path& path) {
return ToUTF8String(path.u8string());
}
diff --git a/src/common/fs/fs_util.h b/src/common/fs/fs_util.h
index ec9950ee7..1ec82eb35 100644
--- a/src/common/fs/fs_util.h
+++ b/src/common/fs/fs_util.h
@@ -47,6 +47,17 @@ concept IsChar = std::same_as<T, char>;
[[nodiscard]] std::string ToUTF8String(std::u8string_view u8_string);
/**
+ * Converts a buffer of bytes to a UTF8-encoded std::string.
+ * This converts from the start of the buffer until the first encountered null-terminator.
+ * If no null-terminator is found, this converts the entire buffer instead.
+ *
+ * @param buffer Buffer of bytes
+ *
+ * @returns UTF-8 encoded std::string.
+ */
+[[nodiscard]] std::string BufferToUTF8String(std::span<const u8> buffer);
+
+/**
* Converts a filesystem path to a UTF-8 encoded std::string.
*
* @param path Filesystem path