early-access version 1670

This commit is contained in:
pineappleEA
2021-05-11 02:22:43 +02:00
parent 1148b01aac
commit 0301e95e45
23 changed files with 452 additions and 240 deletions

View File

@@ -14,8 +14,8 @@ namespace fs = std::filesystem;
// File Operations
bool NewFile(const fs::path& path, u64 size) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -52,8 +52,8 @@ bool NewFile(const fs::path& path, u64 size) {
}
bool RemoveFile(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -86,8 +86,9 @@ bool RemoveFile(const fs::path& path) {
}
bool RenameFile(const fs::path& old_path, const fs::path& new_path) {
if (old_path.empty() || new_path.empty()) {
LOG_ERROR(Common_Filesystem, "One or both input path(s) is empty, old_path={}, new_path={}",
if (!ValidatePath(old_path) || !ValidatePath(new_path)) {
LOG_ERROR(Common_Filesystem,
"One or both input path(s) is not valid, old_path={}, new_path={}",
PathToUTF8String(old_path), PathToUTF8String(new_path));
return false;
}
@@ -129,8 +130,8 @@ bool RenameFile(const fs::path& old_path, const fs::path& new_path) {
std::shared_ptr<IOFile> FileOpen(const fs::path& path, FileAccessMode mode, FileType type,
FileShareFlag flag) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return nullptr;
}
@@ -162,8 +163,8 @@ std::shared_ptr<IOFile> FileOpen(const fs::path& path, FileAccessMode mode, File
// Directory Operations
bool CreateDir(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -196,8 +197,8 @@ bool CreateDir(const fs::path& path) {
}
bool CreateDirs(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -232,8 +233,8 @@ bool CreateParentDirs(const fs::path& path) {
}
bool RemoveDir(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -266,8 +267,8 @@ bool RemoveDir(const fs::path& path) {
}
bool RemoveDirRecursively(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -301,8 +302,8 @@ bool RemoveDirRecursively(const fs::path& path) {
}
bool RemoveDirContentsRecursively(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return false;
}
@@ -353,8 +354,9 @@ bool RemoveDirContentsRecursively(const fs::path& path) {
}
bool RenameDir(const fs::path& old_path, const fs::path& new_path) {
if (old_path.empty() || new_path.empty()) {
LOG_ERROR(Common_Filesystem, "One or both input path(s) is empty, old_path={}, new_path={}",
if (!ValidatePath(old_path) || !ValidatePath(new_path)) {
LOG_ERROR(Common_Filesystem,
"One or both input path(s) is not valid, old_path={}, new_path={}",
PathToUTF8String(old_path), PathToUTF8String(new_path));
return false;
}
@@ -396,8 +398,8 @@ bool RenameDir(const fs::path& old_path, const fs::path& new_path) {
void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable& callback,
DirEntryFilter filter) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return;
}
@@ -452,8 +454,8 @@ void IterateDirEntries(const std::filesystem::path& path, const DirEntryCallable
void IterateDirEntriesRecursively(const std::filesystem::path& path,
const DirEntryCallable& callback, DirEntryFilter filter) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
if (!ValidatePath(path)) {
LOG_ERROR(Common_Filesystem, "Input path is not valid, path={}", PathToUTF8String(path));
return;
}

View File

@@ -20,7 +20,7 @@ class IOFile;
* Creates a new file at path with a specified size.
*
* Failures occur when:
* - Input path is empty
* - 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
@@ -50,7 +50,7 @@ template <typename Path>
* Removes a file at path.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a file
* - Filesystem at path is read only
*
@@ -78,7 +78,7 @@ template <typename Path>
* Renames a file from old_path to new_path.
*
* Failures occur when:
* - One or both input path(s) is empty
* - 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
@@ -117,7 +117,7 @@ template <typename Path1, typename Path2>
* These behaviors are documented in each enum value of FileAccessMode.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a file
* - The file is not opened
*
@@ -158,7 +158,7 @@ template <typename Path>
* If you intend to create the parent directory of a file, use CreateParentDir instead.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - The input path's parent directory does not exist
* - Filesystem at path is read only
*
@@ -190,7 +190,7 @@ template <typename Path>
* Unlike CreateDir, this creates all of input path's parent directories if they do not exist.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem at path is read only
*
* @param path Filesystem path
@@ -265,7 +265,7 @@ template <typename Path>
* Removes a directory at path.
*
* Failures occur when:
* - Input path is empty
* - 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
@@ -294,7 +294,7 @@ template <typename Path>
* Removes all the contents within the given directory and removes the directory itself.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a directory
* - Filesystem at path is read only
*
@@ -322,7 +322,7 @@ template <typename Path>
* Removes all the contents within the given directory without removing the directory itself.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a directory
* - Filesystem at path is read only
*
@@ -350,7 +350,7 @@ template <typename Path>
* Renames a directory from old_path to new_path.
*
* Failures occur when:
* - One or both input path(s) is empty
* - 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
@@ -392,7 +392,7 @@ template <typename Path1, typename Path2>
* If the callback returns false or there is an error, the iteration is immediately halted.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path is not a directory
*
* @param path Filesystem path
@@ -425,7 +425,7 @@ void IterateDirEntries(const Path& path, const DirEntryCallable& callback,
* If the callback returns false or there is an error, the iteration is immediately halted.
*
* Failures occur when:
* - Input path is empty
* - Input path is not valid
* - Filesystem object at path does not exist
* - Filesystem object at path is not a directory
*

View File

@@ -4,10 +4,6 @@
#pragma once
#ifndef MAX_PATH
#define MAX_PATH 260
#endif
// yuzu data directories
#define YUZU_DIR "yuzu"

View File

@@ -37,10 +37,26 @@
#endif
#endif
#ifndef MAX_PATH
#ifdef _WIN32
// This is the maximum number of UTF-16 code units permissible in Windows file paths
#define MAX_PATH 260
#else
// This is the maximum number of UTF-8 code units permissible in all other OSes' file paths
#define MAX_PATH 1024
#endif
#endif
namespace Common::FS {
namespace fs = std::filesystem;
namespace {
constexpr std::array<char8_t, 7> INVALID_CHARS{u':', u'*', u'?', u'"', u'<', u'>', u'|'};
}
/**
* The PathManagerImpl is a singleton allowing to manage the mapping of
* YuzuPath enums to real filesystem paths.
@@ -129,6 +145,41 @@ std::string PathToUTF8String(const fs::path& path) {
return std::string{utf8_string.begin(), utf8_string.end()};
}
bool ValidatePath(const fs::path& path) {
if (path.empty()) {
LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path));
return false;
}
#ifdef _WIN32
if (path.u16string().size() >= MAX_PATH) {
LOG_ERROR(Common_Filesystem, "Input path is too long, path={}", PathToUTF8String(path));
return false;
}
#else
if (path.u8string().size() >= MAX_PATH) {
LOG_ERROR(Common_Filesystem, "Input path is too long, path={}", PathToUTF8String(path));
return false;
}
#endif
for (const auto path_char : path.relative_path().u8string()) {
for (const auto invalid_char : INVALID_CHARS) {
if (path_char == invalid_char) {
LOG_ERROR(Common_Filesystem, "Input path contains invalid characters, path={}",
PathToUTF8String(path));
return false;
}
}
}
return true;
}
fs::path ConcatPath(const fs::path& first, const fs::path& second) {
const bool second_has_dir_sep = IsDirSeparator(second.u8string().front());

View File

@@ -1,4 +1,4 @@
// Copyright 2020 yuzu Emulator Project
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -45,6 +45,35 @@ enum class YuzuPath {
*/
[[nodiscard]] std::string PathToUTF8String(const std::filesystem::path& path);
/**
* Validates a given path.
*
* A given path is valid if it meets these conditions:
* - The path is not empty
* - The path is not too long
* - The path relative to the platform-specific root path does not contain
* any of the following characters: ':', '*', '?', '"', '<', '>', '|'
*
* @param path Filesystem path
*
* @returns True if the path is valid, false otherwise.
*/
[[nodiscard]] bool ValidatePath(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
[[nodiscard]] bool ValidatePath(const Path& path) {
using ValueType = typename Path::value_type;
if constexpr (IsChar<ValueType>) {
return ValidatePath(ToU8String(path));
} else {
return ValidatePath(std::filesystem::path{path});
}
}
#endif
/**
* Concatenates two filesystem paths together.
*