Skip to content

Commit

Permalink
FHU: Switch over win32 file operations to std::filesystem
Browse files Browse the repository at this point in the history
These were broken to varying degrees across the board on win32,
just switch to their std::filesystem as windows doesn't have the
same allocator issues that require their reimplementation.
  • Loading branch information
bylaws committed Apr 10, 2024
1 parent a0f2cae commit ef48700
Showing 1 changed file with 74 additions and 51 deletions.
125 changes: 74 additions & 51 deletions FEXHeaderUtils/FEXHeaderUtils/Filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@
#include <unistd.h>

namespace FHU::Filesystem {
enum class CreateDirectoryResult {
CREATED,
EXISTS,
ERROR,
};

enum class CopyOptions {
NONE,
SKIP_EXISTING,
OVERWRITE_EXISTING,
};

/**
* @brief Check if a filepath exists.
*
Expand All @@ -34,25 +46,27 @@ namespace FHU::Filesystem {
return access(Path.c_str(), F_OK) == 0;
}

/**
* @brief Renames a file and overwrites if it already exists.
*
* @return No error on rename.
*/
[[nodiscard]] inline std::error_code RenameFile(const fextl::string &From, const fextl::string &To) {
return rename(From.c_str(), To.c_str()) == 0 ? std::error_code{} : std::make_error_code(std::errc::io_error);
}

#ifndef _WIN32
inline bool ExistsAt(int FD, const fextl::string &Path) {
return faccessat(FD, Path.c_str(), F_OK, 0) == 0;
}
#endif

enum class CreateDirectoryResult {
CREATED,
EXISTS,
ERROR,
};
/**
* @brief Creates a directory at the provided path.
*
* @param Path The path to create a directory at.
*
* @return Result enum depending.
*/
#ifndef _WIN32
inline CreateDirectoryResult CreateDirectory(const fextl::string &Path) {
auto Result = ::mkdir(Path.c_str(), 0777);
if (Result == 0) {
Expand All @@ -73,18 +87,6 @@ namespace FHU::Filesystem {
// Couldn't create, or the path that existed wasn't a folder.
return CreateDirectoryResult::ERROR;
}
#else
inline CreateDirectoryResult CreateDirectory(const fextl::string &Path) {
std::error_code ec;
if (std::filesystem::exists(Path, ec)) {
return CreateDirectoryResult::EXISTS;
}

return std::filesystem::create_directory(Path, ec) ?
CreateDirectoryResult::CREATED :
CreateDirectoryResult::ERROR;
}
#endif

/**
* @brief Creates a directory tree with the provided path.
Expand Down Expand Up @@ -160,12 +162,6 @@ namespace FHU::Filesystem {
return Path.starts_with('/');
}

enum class CopyOptions {
NONE,
SKIP_EXISTING,
OVERWRITE_EXISTING,
};

/**
* @brief Copy a file from a location to another
*
Expand All @@ -177,7 +173,6 @@ namespace FHU::Filesystem {
*
* @return True if the copy succeeded, false otherwise.
*/
#ifndef _WIN32
inline bool CopyFile(const fextl::string &From, const fextl::string &To, CopyOptions Options = CopyOptions::NONE) {
const bool DestExists = Exists(To);
if (Options == CopyOptions::SKIP_EXISTING && DestExists) {
Expand Down Expand Up @@ -225,30 +220,6 @@ namespace FHU::Filesystem {

return false;
}
#else
inline bool CopyFile(const fextl::string &From, const fextl::string &To, CopyOptions Options = CopyOptions::NONE) {
std::filesystem::copy_options options{};
if (Options == CopyOptions::SKIP_EXISTING) {
options = std::filesystem::copy_options::skip_existing;
}
else if (Options == CopyOptions::OVERWRITE_EXISTING) {
options = std::filesystem::copy_options::overwrite_existing;
}

std::error_code ec;
return std::filesystem::copy_file(From, To, options, ec);
}

#endif

/**
* @brief Renames a file and overwrites if it already exists.
*
* @return No error on rename.
*/
[[nodiscard]] inline std::error_code RenameFile(const fextl::string &From, const fextl::string &To) {
return rename(From.c_str(), To.c_str()) == 0 ? std::error_code{} : std::make_error_code(std::errc::io_error);
}

inline fextl::string LexicallyNormal(const fextl::string &Path) {
const auto PathSize = Path.size();
Expand Down Expand Up @@ -353,11 +324,63 @@ namespace FHU::Filesystem {
NeedsFinalSeparator ? "/" : "");
}

#ifndef _WIN32
inline char *Absolute(const char *Path, char Fill[PATH_MAX]) {
return realpath(Path, Fill);
}
#else
inline fextl::string PathToString(const std::filesystem::path &path) {
return path.string<char, std::char_traits<char>, fextl::FEXAlloc<char>>();
}

inline CreateDirectoryResult CreateDirectory(const fextl::string &Path) {
std::error_code ec;
if (std::filesystem::exists(Path, ec)) {
return CreateDirectoryResult::EXISTS;
}

return std::filesystem::create_directory(Path, ec) ?
CreateDirectoryResult::CREATED :
CreateDirectoryResult::ERROR;
}

inline bool CreateDirectories(const fextl::string &Path) {
std::error_code ec;
return std::filesystem::exists(Path, ec) || std::filesystem::create_directories(Path, ec);
}

inline fextl::string GetFilename(const fextl::string &Path) {
return PathToString(std::filesystem::path(Path).filename());
}

inline fextl::string ParentPath(const fextl::string &Path) {
return PathToString(std::filesystem::path(Path).parent_path());
}

inline bool IsRelative(const std::string_view Path) {
return std::filesystem::path(Path).is_relative();
}

inline bool IsAbsolute(const std::string_view Path) {
return std::filesystem::path(Path).is_absolute();
}

inline bool CopyFile(const fextl::string &From, const fextl::string &To, CopyOptions Options = CopyOptions::NONE) {
std::filesystem::copy_options options{};
if (Options == CopyOptions::SKIP_EXISTING) {
options = std::filesystem::copy_options::skip_existing;
}
else if (Options == CopyOptions::OVERWRITE_EXISTING) {
options = std::filesystem::copy_options::overwrite_existing;
}

std::error_code ec;
return std::filesystem::copy_file(From, To, options, ec);
}

inline fextl::string LexicallyNormal(const fextl::string &Path) {
return PathToString(std::filesystem::path(Path).lexically_normal());
}

inline char *Absolute(const char *Path, char Fill[PATH_MAX]) {
std::error_code ec;
const auto PathAbsolute = std::filesystem::absolute(Path, ec);
Expand Down

0 comments on commit ef48700

Please sign in to comment.