summaryrefslogtreecommitdiff
path: root/src/common/fs/fs.h
diff options
context:
space:
mode:
authorMorph <39850852+Morph1984@users.noreply.github.com>2021-05-25 19:32:56 -0400
committerGitHub <noreply@github.com>2021-05-25 19:32:56 -0400
commit065867e2c24e9856c360fc2d6b9a86c92aedc43e (patch)
tree7964e85ef4f01a3c2b8f44e850f37b384405b930 /src/common/fs/fs.h
parent08a5cf0b5bd43f63122cb722f5ecce89ab01a160 (diff)
common: fs: Rework the Common Filesystem interface to make use of std::filesystem (#6270)
* common: fs: fs_types: Create filesystem types Contains various filesystem types used by the Common::FS library * common: fs: fs_util: Add std::string to std::u8string conversion utility * common: fs: path_util: Add utlity functions for paths Contains various utility functions for getting or manipulating filesystem paths used by the Common::FS library * common: fs: file: Rewrite the IOFile implementation * common: fs: Reimplement Common::FS library using std::filesystem * common: fs: fs_paths: Add fs_paths to replace common_paths * common: fs: path_util: Add the rest of the path functions * common: Remove the previous Common::FS implementation * general: Remove unused fs includes * string_util: Remove unused function and include * nvidia_flags: Migrate to the new Common::FS library * settings: Migrate to the new Common::FS library * logging: backend: Migrate to the new Common::FS library * core: Migrate to the new Common::FS library * perf_stats: Migrate to the new Common::FS library * reporter: Migrate to the new Common::FS library * telemetry_session: Migrate to the new Common::FS library * key_manager: Migrate to the new Common::FS library * bis_factory: Migrate to the new Common::FS library * registered_cache: Migrate to the new Common::FS library * xts_archive: Migrate to the new Common::FS library * service: acc: Migrate to the new Common::FS library * applets/profile: Migrate to the new Common::FS library * applets/web: Migrate to the new Common::FS library * service: filesystem: Migrate to the new Common::FS library * loader: Migrate to the new Common::FS library * gl_shader_disk_cache: Migrate to the new Common::FS library * nsight_aftermath_tracker: Migrate to the new Common::FS library * vulkan_library: Migrate to the new Common::FS library * configure_debug: Migrate to the new Common::FS library * game_list_worker: Migrate to the new Common::FS library * config: Migrate to the new Common::FS library * configure_filesystem: Migrate to the new Common::FS library * configure_per_game_addons: Migrate to the new Common::FS library * configure_profile_manager: Migrate to the new Common::FS library * configure_ui: Migrate to the new Common::FS library * input_profiles: Migrate to the new Common::FS library * yuzu_cmd: config: Migrate to the new Common::FS library * yuzu_cmd: Migrate to the new Common::FS library * vfs_real: Migrate to the new Common::FS library * vfs: Migrate to the new Common::FS library * vfs_libzip: Migrate to the new Common::FS library * service: bcat: Migrate to the new Common::FS library * yuzu: main: Migrate to the new Common::FS library * vfs_real: Delete the contents of an existing file in CreateFile Current usages of CreateFile expect to delete the contents of an existing file, retain this behavior for now. * input_profiles: Don't iterate the input profile dir if it does not exist Silences an error produced in the log if the directory does not exist. * game_list_worker: Skip parsing file if the returned VfsFile is nullptr Prevents crashes in GetLoader when the virtual file is nullptr * common: fs: Validate paths for path length * service: filesystem: Open the mod load directory as read only
Diffstat (limited to 'src/common/fs/fs.h')
-rw-r--r--src/common/fs/fs.h582
1 files changed, 582 insertions, 0 deletions
diff --git a/src/common/fs/fs.h b/src/common/fs/fs.h
new file mode 100644
index 000000000..f6f256349
--- /dev/null
+++ b/src/common/fs/fs.h
@@ -0,0 +1,582 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <filesystem>
+#include <memory>
+
+#include "common/fs/fs_types.h"
+#include "common/fs/fs_util.h"
+
+namespace Common::FS {
+
+class IOFile;
+
+// File Operations
+
+/**
+ * Creates a new file at path with the specified size.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - The input path's parent directory does not exist
+ * - Filesystem object at path exists
+ * - Filesystem at path is read only
+ *
+ * @param path Filesystem path
+ * @param size File size
+ *
+ * @returns True if the file creation succeeds, false otherwise.
+ */
+[[nodiscard]] bool NewFile(const std::filesystem::path& path, u64 size = 0);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool NewFile(const Path& path, u64 size = 0) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return NewFile(ToU8String(path), size);
+ } else {
+ return NewFile(std::filesystem::path{path}, size);
+ }
+}
+#endif
+
+/**
+ * Removes a file at path.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - Filesystem object at path is not a 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);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool RemoveFile(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return RemoveFile(ToU8String(path));
+ } else {
+ return RemoveFile(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Renames a file from old_path to new_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 new_path exists
+ * - Filesystem at either path is read only
+ *
+ * @param old_path Old filesystem path
+ * @param new_path New filesystem path
+ *
+ * @returns True if file rename succeeds, false otherwise.
+ */
+[[nodiscard]] bool RenameFile(const std::filesystem::path& old_path,
+ const std::filesystem::path& new_path);
+
+#ifdef _WIN32
+template <typename Path1, typename Path2>
+[[nodiscard]] bool RenameFile(const Path1& old_path, const Path2& new_path) {
+ using ValueType1 = typename Path1::value_type;
+ using ValueType2 = typename Path2::value_type;
+ if constexpr (IsChar<ValueType1> && IsChar<ValueType2>) {
+ return RenameFile(ToU8String(old_path), ToU8String(new_path));
+ } else if constexpr (IsChar<ValueType1> && !IsChar<ValueType2>) {
+ return RenameFile(ToU8String(old_path), new_path);
+ } else if constexpr (!IsChar<ValueType1> && IsChar<ValueType2>) {
+ return RenameFile(old_path, ToU8String(new_path));
+ } else {
+ return RenameFile(std::filesystem::path{old_path}, std::filesystem::path{new_path});
+ }
+}
+#endif
+
+/**
+ * Opens a file at path with the specified file access mode.
+ * This function behaves differently depending on the FileAccessMode.
+ * These behaviors are documented in each enum value of FileAccessMode.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - Filesystem object at path is not a file
+ * - The file is not opened
+ *
+ * @param path Filesystem path
+ * @param mode File access mode
+ * @param type File type, default is BinaryFile. Use TextFile to open the file as a text file
+ * @param flag (Windows only) File-share access flag, default is ShareReadOnly
+ *
+ * @returns A shared pointer to the opened file. Returns nullptr on failure.
+ */
+[[nodiscard]] std::shared_ptr<IOFile> FileOpen(const std::filesystem::path& path,
+ FileAccessMode mode,
+ FileType type = FileType::BinaryFile,
+ FileShareFlag flag = FileShareFlag::ShareReadOnly);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] std::shared_ptr<IOFile> FileOpen(const Path& path, FileAccessMode mode,
+ FileType type = FileType::BinaryFile,
+ FileShareFlag flag = FileShareFlag::ShareReadOnly) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return FileOpen(ToU8String(path), mode, type, flag);
+ } else {
+ return FileOpen(std::filesystem::path{path}, mode, type, flag);
+ }
+}
+#endif
+
+// Directory Operations
+
+/**
+ * Creates a directory at path.
+ * Note that this function will *always* assume that the input path is a directory. For example,
+ * if the input path is /path/to/directory/file.txt, it will create a directory called "file.txt".
+ * If you intend to create the parent directory of a file, use CreateParentDir instead.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - The input path's parent directory does not exist
+ * - Filesystem at path is read only
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if directory creation succeeds or directory already exists, false otherwise.
+ */
+[[nodiscard]] bool CreateDir(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool CreateDir(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return CreateDir(ToU8String(path));
+ } else {
+ return CreateDir(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Recursively creates a directory at path.
+ * Note that this function will *always* assume that the input path is a directory. For example,
+ * if the input path is /path/to/directory/file.txt, it will create a directory called "file.txt".
+ * If you intend to create the parent directory of a file, use CreateParentDirs instead.
+ * Unlike CreateDir, this creates all of input path's parent directories if they do not exist.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - Filesystem at path is read only
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if directory creation succeeds or directory already exists, false otherwise.
+ */
+[[nodiscard]] bool CreateDirs(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool CreateDirs(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return CreateDirs(ToU8String(path));
+ } else {
+ return CreateDirs(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Creates the parent directory of a given path.
+ * This function calls CreateDir(path.parent_path()), see CreateDir for more details.
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if directory creation succeeds or directory already exists, false otherwise.
+ */
+[[nodiscard]] bool CreateParentDir(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool CreateParentDir(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return CreateParentDir(ToU8String(path));
+ } else {
+ return CreateParentDir(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Recursively creates the parent directory of a given path.
+ * This function calls CreateDirs(path.parent_path()), see CreateDirs for more details.
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if directory creation succeeds or directory already exists, false otherwise.
+ */
+[[nodiscard]] bool CreateParentDirs(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool CreateParentDirs(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return CreateParentDirs(ToU8String(path));
+ } else {
+ return CreateParentDirs(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Removes a directory at path.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - Filesystem object at path is not a directory
+ * - The given directory is not empty
+ * - Filesystem at path is read only
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if directory removal succeeds or directory does not exist, false otherwise.
+ */
+[[nodiscard]] bool RemoveDir(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool RemoveDir(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return RemoveDir(ToU8String(path));
+ } else {
+ return RemoveDir(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Removes all the contents within the given directory and removes the directory itself.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - Filesystem object at path is not a directory
+ * - Filesystem at path is read only
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if the directory and all of its contents are removed successfully, false otherwise.
+ */
+[[nodiscard]] bool RemoveDirRecursively(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool RemoveDirRecursively(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return RemoveDirRecursively(ToU8String(path));
+ } else {
+ return RemoveDirRecursively(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Removes all the contents within the given directory without removing the directory itself.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - Filesystem object at path is not a directory
+ * - Filesystem at path is read only
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if all of the directory's contents are removed successfully, false otherwise.
+ */
+[[nodiscard]] bool RemoveDirContentsRecursively(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool RemoveDirContentsRecursively(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return RemoveDirContentsRecursively(ToU8String(path));
+ } else {
+ return RemoveDirContentsRecursively(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Renames a directory from old_path to new_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 directory
+ * - Filesystem object at new_path exists
+ * - Filesystem at either path is read only
+ *
+ * @param old_path Old filesystem path
+ * @param new_path New filesystem path
+ *
+ * @returns True if directory rename succeeds, false otherwise.
+ */
+[[nodiscard]] bool RenameDir(const std::filesystem::path& old_path,
+ const std::filesystem::path& new_path);
+
+#ifdef _WIN32
+template <typename Path1, typename Path2>
+[[nodiscard]] bool RenameDir(const Path1& old_path, const Path2& new_path) {
+ using ValueType1 = typename Path1::value_type;
+ using ValueType2 = typename Path2::value_type;
+ if constexpr (IsChar<ValueType1> && IsChar<ValueType2>) {
+ return RenameDir(ToU8String(old_path), ToU8String(new_path));
+ } else if constexpr (IsChar<ValueType1> && !IsChar<ValueType2>) {
+ return RenameDir(ToU8String(old_path), new_path);
+ } else if constexpr (!IsChar<ValueType1> && IsChar<ValueType2>) {
+ return RenameDir(old_path, ToU8String(new_path));
+ } else {
+ return RenameDir(std::filesystem::path{old_path}, std::filesystem::path{new_path});
+ }
+}
+#endif
+
+/**
+ * Iterates over the directory entries of a given directory.
+ * This does not iterate over the sub-directories of the given directory.
+ * The DirEntryCallable callback is called for each visited directory entry.
+ * A filter can be set to control which directory entries are visited based on their type.
+ * By default, both files and directories are visited.
+ * If the callback returns false or there is an error, the iteration is immediately halted.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - Filesystem object at path is not a directory
+ *
+ * @param path Filesystem path
+ * @param callback Callback to be called for each visited directory entry
+ * @param filter Directory entry type filter
+ */
+void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable& callback,
+ DirEntryFilter filter = DirEntryFilter::All);
+
+#ifdef _WIN32
+template <typename Path>
+void IterateDirEntries(const Path& path, const DirEntryCallable& callback,
+ DirEntryFilter filter = DirEntryFilter::All) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ IterateDirEntries(ToU8String(path), callback, filter);
+ } else {
+ IterateDirEntries(std::filesystem::path{path}, callback, filter);
+ }
+}
+#endif
+
+/**
+ * Iterates over the directory entries of a given directory and its sub-directories.
+ * The DirEntryCallable callback is called for each visited directory entry.
+ * A filter can be set to control which directory entries are visited based on their type.
+ * By default, both files and directories are visited.
+ * If the callback returns false or there is an error, the iteration is immediately halted.
+ *
+ * Failures occur when:
+ * - Input path is not valid
+ * - Filesystem object at path does not exist
+ * - Filesystem object at path is not a directory
+ *
+ * @param path Filesystem path
+ * @param callback Callback to be called for each visited directory entry
+ * @param filter Directory entry type filter
+ */
+void IterateDirEntriesRecursively(const std::filesystem::path& path,
+ const DirEntryCallable& callback,
+ DirEntryFilter filter = DirEntryFilter::All);
+
+#ifdef _WIN32
+template <typename Path>
+void IterateDirEntriesRecursively(const Path& path, const DirEntryCallable& callback,
+ DirEntryFilter filter = DirEntryFilter::All) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ IterateDirEntriesRecursively(ToU8String(path), callback, filter);
+ } else {
+ IterateDirEntriesRecursively(std::filesystem::path{path}, callback, filter);
+ }
+}
+#endif
+
+// Generic Filesystem Operations
+
+/**
+ * Returns whether a filesystem object at path exists.
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if a filesystem object at path exists, false otherwise.
+ */
+[[nodiscard]] bool Exists(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool Exists(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return Exists(ToU8String(path));
+ } else {
+ return Exists(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Returns whether a filesystem object at path is a file.
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if a filesystem object at path is a file, false otherwise.
+ */
+[[nodiscard]] bool IsFile(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool IsFile(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return IsFile(ToU8String(path));
+ } else {
+ return IsFile(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Returns whether a filesystem object at path is a directory.
+ *
+ * @param path Filesystem path
+ *
+ * @returns True if a filesystem object at path is a directory, false otherwise.
+ */
+[[nodiscard]] bool IsDir(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool IsDir(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return IsDir(ToU8String(path));
+ } else {
+ return IsDir(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Gets the current working directory.
+ *
+ * @returns The current working directory. Returns an empty path on failure.
+ */
+[[nodiscard]] std::filesystem::path GetCurrentDir();
+
+/**
+ * Sets the current working directory to path.
+ *
+ * @returns True if the current working directory is successfully set, false otherwise.
+ */
+[[nodiscard]] bool SetCurrentDir(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] bool SetCurrentDir(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return SetCurrentDir(ToU8String(path));
+ } else {
+ return SetCurrentDir(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Gets the entry type of the filesystem object at path.
+ *
+ * @param path Filesystem path
+ *
+ * @returns The entry type of the filesystem object. Returns file_type::not_found on failure.
+ */
+[[nodiscard]] std::filesystem::file_type GetEntryType(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] std::filesystem::file_type GetEntryType(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return GetEntryType(ToU8String(path));
+ } else {
+ return GetEntryType(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Gets the size of the filesystem object at path.
+ *
+ * @param path Filesystem path
+ *
+ * @returns The size in bytes of the filesystem object. Returns 0 on failure.
+ */
+[[nodiscard]] u64 GetSize(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] u64 GetSize(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return GetSize(ToU8String(path));
+ } else {
+ return GetSize(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Gets the free space size of the filesystem at path.
+ *
+ * @param path Filesystem path
+ *
+ * @returns The free space size in bytes of the filesystem at path. Returns 0 on failure.
+ */
+[[nodiscard]] u64 GetFreeSpaceSize(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] u64 GetFreeSpaceSize(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return GetFreeSpaceSize(ToU8String(path));
+ } else {
+ return GetFreeSpaceSize(std::filesystem::path{path});
+ }
+}
+#endif
+
+/**
+ * Gets the total capacity of the filesystem at path.
+ *
+ * @param path Filesystem path
+ *
+ * @returns The total capacity in bytes of the filesystem at path. Returns 0 on failure.
+ */
+[[nodiscard]] u64 GetTotalSpaceSize(const std::filesystem::path& path);
+
+#ifdef _WIN32
+template <typename Path>
+[[nodiscard]] u64 GetTotalSpaceSize(const Path& path) {
+ if constexpr (IsChar<typename Path::value_type>) {
+ return GetTotalSpaceSize(ToU8String(path));
+ } else {
+ return GetTotalSpaceSize(std::filesystem::path{path});
+ }
+}
+#endif
+
+} // namespace Common::FS