From 81b1b71993473b31321c8ff2d0dd0b267848a968 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 19 Jun 2021 03:43:16 -0400 Subject: [PATCH 1/5] common: fs: Remove [[nodiscard]] attribute on Remove* functions There are a lot of scenarios where we don't particularly care whether or not the removal operation and just simply attempt a removal. As such, removing the [[nodiscard]] attribute is best for these functions. --- src/common/fs/fs.h | 16 ++++++------- src/common/logging/backend.cpp | 2 +- src/core/hle/service/bcat/backend/boxcat.cpp | 4 ++-- .../nsight_aftermath_tracker.cpp | 2 +- .../configure_per_game_addons.cpp | 4 ++-- src/yuzu/main.cpp | 24 +++++++++---------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/common/fs/fs.h b/src/common/fs/fs.h index f6f256349..cf7dfffcc 100644 --- a/src/common/fs/fs.h +++ b/src/common/fs/fs.h @@ -55,11 +55,11 @@ template * * @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 -[[nodiscard]] bool RemoveFile(const Path& path) { +bool RemoveFile(const Path& path) { if constexpr (IsChar) { return RemoveFile(ToU8String(path)); } else { @@ -251,11 +251,11 @@ template * * @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 -[[nodiscard]] bool RemoveDir(const Path& path) { +bool RemoveDir(const Path& path) { if constexpr (IsChar) { return RemoveDir(ToU8String(path)); } else { @@ -276,11 +276,11 @@ template * * @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 -[[nodiscard]] bool RemoveDirRecursively(const Path& path) { +bool RemoveDirRecursively(const Path& path) { if constexpr (IsChar) { return RemoveDirRecursively(ToU8String(path)); } else { @@ -301,11 +301,11 @@ template * * @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 -[[nodiscard]] bool RemoveDirContentsRecursively(const Path& path) { +bool RemoveDirContentsRecursively(const Path& path) { if constexpr (IsChar) { return RemoveDirContentsRecursively(ToU8String(path)); } else { diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index d5cff400f..47dba48ca 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -159,7 +159,7 @@ FileBackend::FileBackend(const std::filesystem::path& filename) { // Existence checks are done within the functions themselves. // We don't particularly care if these succeed or not. - void(FS::RemoveFile(old_filename)); + FS::RemoveFile(old_filename); void(FS::RenameFile(filename, old_filename)); file = diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp index a2844ea8c..dc15cf58b 100644 --- a/src/core/hle/service/bcat/backend/boxcat.cpp +++ b/src/core/hle/service/bcat/backend/boxcat.cpp @@ -313,7 +313,7 @@ void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGe LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { - void(Common::FS::RemoveFile(zip_path)); + Common::FS::RemoveFile(zip_path); } HandleDownloadDisplayResult(applet_manager, res); @@ -445,7 +445,7 @@ std::optional> Boxcat::GetLaunchParameter(TitleIDVersion title) LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { - void(Common::FS::RemoveFile(bin_file_path)); + Common::FS::RemoveFile(bin_file_path); } HandleDownloadDisplayResult(applet_manager, res); diff --git a/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp index f0ee76519..758c038ba 100644 --- a/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp +++ b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp @@ -50,7 +50,7 @@ NsightAftermathTracker::NsightAftermathTracker() { } dump_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::LogDir) / "gpucrash"; - void(Common::FS::RemoveDirRecursively(dump_dir)); + Common::FS::RemoveDirRecursively(dump_dir); if (!Common::FS::CreateDir(dump_dir)) { LOG_ERROR(Render_Vulkan, "Failed to create Nsight Aftermath dump directory"); return; diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 9b709d405..ebb0f411c 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp @@ -79,8 +79,8 @@ void ConfigurePerGameAddons::ApplyConfiguration() { std::sort(disabled_addons.begin(), disabled_addons.end()); std::sort(current.begin(), current.end()); if (disabled_addons != current) { - void(Common::FS::RemoveFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / - "game_list" / fmt::format("{:016X}.pv.txt", title_id))); + Common::FS::RemoveFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / + "game_list" / fmt::format("{:016X}.pv.txt", title_id)); } Settings::values.disabled_addons[title_id] = disabled_addons; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index d4c7d2c0b..75ab5ef44 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -194,10 +194,10 @@ static void RemoveCachedContents() { const auto offline_legal_information = cache_dir / "offline_web_applet_legal_information"; const auto offline_system_data = cache_dir / "offline_web_applet_system_data"; - void(Common::FS::RemoveDirRecursively(offline_fonts)); - void(Common::FS::RemoveDirRecursively(offline_manual)); - void(Common::FS::RemoveDirRecursively(offline_legal_information)); - void(Common::FS::RemoveDirRecursively(offline_system_data)); + Common::FS::RemoveDirRecursively(offline_fonts); + Common::FS::RemoveDirRecursively(offline_manual); + Common::FS::RemoveDirRecursively(offline_legal_information); + Common::FS::RemoveDirRecursively(offline_system_data); } GMainWindow::GMainWindow() @@ -1743,8 +1743,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT RemoveAddOnContent(program_id, entry_type); break; } - void(Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / - "game_list")); + Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / + "game_list"); game_list->PopulateAsync(UISettings::values.game_dirs); } @@ -2213,8 +2213,8 @@ void GMainWindow::OnMenuInstallToNAND() { : tr("%n file(s) failed to install\n", "", failed_files.size())); QMessageBox::information(this, tr("Install Results"), install_results); - void(Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / - "game_list")); + Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / + "game_list"); game_list->PopulateAsync(UISettings::values.game_dirs); ui.action_Install_File_NAND->setEnabled(true); } @@ -2846,7 +2846,7 @@ void GMainWindow::MigrateConfigFiles() { LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination); if (!Common::FS::RenameFile(origin, destination)) { // Delete the old config file if one already exists in the new location. - void(Common::FS::RemoveFile(origin)); + Common::FS::RemoveFile(origin); } } } @@ -3040,9 +3040,9 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { const auto keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir); - void(Common::FS::RemoveFile(keys_dir / "prod.keys_autogenerated")); - void(Common::FS::RemoveFile(keys_dir / "console.keys_autogenerated")); - void(Common::FS::RemoveFile(keys_dir / "title.keys_autogenerated")); + Common::FS::RemoveFile(keys_dir / "prod.keys_autogenerated"); + Common::FS::RemoveFile(keys_dir / "console.keys_autogenerated"); + Common::FS::RemoveFile(keys_dir / "title.keys_autogenerated"); } Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); From cf0b9d1de2dd895de3ebc08b6399d8239f7096f7 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 19 Jun 2021 03:48:02 -0400 Subject: [PATCH 2/5] common: fs: file: Remove [[nodiscard]] attribute from Flush Similarly, Flush() is typically called to attempt to flush a file into the disk. In the one case where this is used, we do not care whether the flush has succeeded or not, making [[nodiscard]] unnecessary. --- src/common/fs/file.h | 4 ++-- src/common/logging/backend.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/fs/file.h b/src/common/fs/file.h index 0f10b6003..087b2993a 100644 --- a/src/common/fs/file.h +++ b/src/common/fs/file.h @@ -394,11 +394,11 @@ public: [[nodiscard]] size_t WriteString(std::span string) const; /** - * Flushes any unwritten buffered data into the file. + * Attempts to flush any unwritten buffered data into the file and flush the file into the disk. * * @returns True if the flush was successful, false otherwise. */ - [[nodiscard]] bool Flush() const; + bool Flush() const; /** * Resizes the file to a given size. diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 47dba48ca..47ce06478 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -186,7 +186,7 @@ void FileBackend::Write(const Entry& entry) { bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n')); if (entry.log_level >= Level::Error) { - void(file->Flush()); + file->Flush(); } } From 76b2313b25e2fd33a508f63137d5113e1ca85150 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 19 Jun 2021 03:49:11 -0400 Subject: [PATCH 3/5] common: fs: Amend IsFile check in FileOpen / (Write/Append)StringToFile This check was preventing files with the Write or Append file access modes from being created, as per the documented behavior in FileAccessMode. This amends the check to test for the existence of a filesystem object prior to checking whether it is a regular file. Thanks to liushuyu for pointing out that removing the check altogether would not guard against attempting to open non-regular files such as directories, symlinks, FIFO (pipes), sockets, block devices, or character devices. The documentation has also been updated for these functions to clarify that a file refers to a regular file. --- src/common/fs/file.cpp | 4 ++-- src/common/fs/file.h | 8 +++++--- src/common/fs/fs.cpp | 5 +++-- src/common/fs/fs.h | 4 ++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp index 710e88b39..077f34995 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; } diff --git a/src/common/fs/file.h b/src/common/fs/file.h index 087b2993a..588fe619d 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 /** * 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 /** * 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 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 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 cf7dfffcc..a6c993962 100644 --- a/src/common/fs/fs.h +++ b/src/common/fs/fs.h @@ -110,8 +110,8 @@ template * * 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 From 0394893354dc76e3fbbcc149aa677deabb72ee5e Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 19 Jun 2021 06:25:53 -0400 Subject: [PATCH 4/5] vfs_real: Fix Mode to FileAccessMode conversion These enforce requiring the file to exist prior to opening. --- src/core/file_sys/vfs_real.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index d0b8fd046..3dad54f49 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -24,17 +24,12 @@ constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(Mode mode) { case Mode::Read: return FS::FileAccessMode::Read; case Mode::Write: - return FS::FileAccessMode::Write; case Mode::ReadWrite: - return FS::FileAccessMode::ReadWrite; case Mode::Append: - return FS::FileAccessMode::Append; case Mode::ReadAppend: - return FS::FileAccessMode::ReadAppend; case Mode::WriteAppend: - return FS::FileAccessMode::Append; case Mode::All: - return FS::FileAccessMode::ReadAppend; + return FS::FileAccessMode::ReadWrite; default: return {}; } From 2fa207058ba6cb1c4d519942e5543bd942f03f6c Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Tue, 22 Jun 2021 15:06:17 -0400 Subject: [PATCH 5/5] common: fs: Add a description of a regular file in IsFile This provides a more concrete example of what a regular file is and isn't. --- src/common/fs/fs.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/common/fs/fs.h b/src/common/fs/fs.h index a6c993962..183126de3 100644 --- a/src/common/fs/fs.h +++ b/src/common/fs/fs.h @@ -48,7 +48,7 @@ template * * 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 @@ -74,7 +74,7 @@ bool RemoveFile(const Path& 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 * @@ -435,11 +435,13 @@ template #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);