fix(libkernel): unlink a dangling Windows directory symbolic link

sceKernelUnlink takes its Windows directory-link path only when
std::filesystem::symlink_status reports a directory, but MinGW's
symlink_status follows the link. A directory symbolic link whose target
is missing therefore looked like a file, went to the file delete, and
failed with EACCES, because Windows removes a directory link only
through RemoveDirectoryW. guest_filesystem stops there on any Windows
host that may create symbolic links.

The directory path is now also taken when the link itself carries both
FILE_ATTRIBUTE_DIRECTORY and FILE_ATTRIBUTE_REPARSE_POINT, which
GetFileAttributesW reports without following the link.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
JJenkxandClaude Opus 5.5 committed 2026-10-31 18:57:56 -04:00
1 parent 7a5d9bf02a
commit b476f50b8e
1 file changed
+7 -1
+7 -1
View File
@@ -488,7 +488,13 @@ int APS5_VABI sceKernelUnlink(const char* path) {
if (const int error = ResolvePathError_nid_no_patch(path, native)) return SceKernelError(error);
constexpr int GuestEperm = 1;
std::error_code error;
if (std::filesystem::is_directory(std::filesystem::symlink_status(native, error))) {
bool directory = std::filesystem::is_directory(std::filesystem::symlink_status(native, error));
#ifdef _WIN32
constexpr DWORD DirectoryLink = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
const DWORD linkAttributes = GetFileAttributesW(native.c_str());
if (linkAttributes != INVALID_FILE_ATTRIBUTES && (linkAttributes & DirectoryLink) == DirectoryLink) directory = true;
#endif
if (directory) {
#ifdef _WIN32
if (native.has_filename()) {
WIN32_FIND_DATAW found{};