diff --git a/common/FileSystem.cpp b/common/FileSystem.cpp index e162a55599..46940388b4 100644 --- a/common/FileSystem.cpp +++ b/common/FileSystem.cpp @@ -1961,6 +1961,26 @@ bool FileSystem::SetPathCompression(const char* path, bool enable) return result; } +bool FileSystem::CreateSymLink(const char* link, const char* target) +{ + // convert to wide string + const std::wstring wlink = GetWin32Path(link); + if (wlink.empty()) + return false; + + const std::wstring wtarget = GetWin32Path(target); + if (wtarget.empty()) + return false; + + // check if it's a directory + DWORD flags = 0; + if (DirectoryExists(target)) + flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; + + // create the symbolic link + return CreateSymbolicLinkW(wlink.c_str(), wtarget.c_str(), flags) != 0; +} + bool FileSystem::IsSymbolicLink(const char* path) { // convert to wide string @@ -2541,6 +2561,11 @@ bool FileSystem::SetPathCompression(const char* path, bool enable) return false; } +bool FileSystem::CreateSymLink(const char* link, const char* target) +{ + return symlink(target, link) == 0; +} + bool FileSystem::IsSymbolicLink(const char* path) { struct stat sysStatData; diff --git a/common/FileSystem.h b/common/FileSystem.h index 6b7fe1806c..f731542b5a 100644 --- a/common/FileSystem.h +++ b/common/FileSystem.h @@ -178,6 +178,10 @@ namespace FileSystem /// Does nothing and returns false on non-Windows platforms. bool SetPathCompression(const char* path, bool enable); + // Creates a symbolic link. Note that on Windows this requires elevated + // privileges so this is mostly useful for testing purposes. + bool CreateSymLink(const char* link, const char* target); + /// Checks if a file or directory is a symbolic link. bool IsSymbolicLink(const char* path); diff --git a/tests/ctest/common/filesystem_tests.cpp b/tests/ctest/common/filesystem_tests.cpp index eaafc74a53..d0fd9b8930 100644 --- a/tests/ctest/common/filesystem_tests.cpp +++ b/tests/ctest/common/filesystem_tests.cpp @@ -7,8 +7,6 @@ #ifdef __linux__ -#include - static std::optional create_test_directory() { for (u16 i = 0; i < UINT16_MAX; i++) @@ -42,7 +40,7 @@ TEST(FileSystem, RecursiveDeleteDirectoryDontFollowSymbolicLinks) std::string dir_to_delete = Path::Combine(*test_dir, "dir_to_delete"); ASSERT_TRUE(FileSystem::CreateDirectoryPath(dir_to_delete.c_str(), false)); std::string symlink_path = Path::Combine(dir_to_delete, "link"); - ASSERT_EQ(symlink(target_dir.c_str(), symlink_path.c_str()), 0); + ASSERT_TRUE(FileSystem::CreateSymLink(symlink_path.c_str(), target_dir.c_str())); // Delete the directory containing the symlink. ASSERT_TRUE(dir_to_delete.starts_with("/tmp/pcsx2_filesystem_test_"));