From cabd834bc5448eadb0a6654d56b07d39387876b5 Mon Sep 17 00:00:00 2001 From: Evgeniy Kazarin Date: Sun, 18 Oct 2026 06:20:03 +0300 Subject: [PATCH 1/4] perf(libc): avoid repeated Windows path component scans --- core/libs/prx/libc/src/General.cpp | 49 +++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/core/libs/prx/libc/src/General.cpp b/core/libs/prx/libc/src/General.cpp index ff92739719bf..f15ac49ac95d 100644 --- a/core/libs/prx/libc/src/General.cpp +++ b/core/libs/prx/libc/src/General.cpp @@ -85,7 +85,35 @@ struct NameMatch { bool ambiguous = false; }; +#ifdef _WIN32 +std::error_code MatchNamesWindows(const std::filesystem::path& directory, std::span names) { + for (auto& name : names) { + const auto pattern = directory / name.name; + WIN32_FIND_DATAW data{}; + const auto handle = FindFirstFileExW(pattern.c_str(), FindExInfoBasic, &data, FindExSearchNameMatch, nullptr, 0); + if (handle == INVALID_HANDLE_VALUE) { + const auto error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND || error == ERROR_NO_MORE_FILES) continue; + return {static_cast(error), std::system_category()}; + } + const std::unique_ptr owner(handle, &FindClose); + do { + const auto filename = std::filesystem::path(data.cFileName); + if (!SameName(filename.string(), name.name)) continue; + name.ambiguous = name.ambiguous || name.path.has_value(); + name.path = directory / filename; + } while (FindNextFileW(handle, &data)); + const auto error = GetLastError(); + if (error != ERROR_NO_MORE_FILES) return {static_cast(error), std::system_category()}; + } + return {}; +} +#endif + std::error_code MatchNames(const std::filesystem::path& directory, std::span names) { +#ifdef _WIN32 + return MatchNamesWindows(directory, names); +#else std::error_code error; std::filesystem::directory_iterator entry(directory, error), end; for (; !error && entry != end; entry.increment(error)) { @@ -97,6 +125,7 @@ std::error_code MatchNames(const std::filesystem::path& directory, std::span& relative, bool module = false) { const auto direct = Child(root, JoinNames(relative)); std::error_code error; + auto first = relative.begin(); +#ifdef _WIN32 + const auto attributes = GetFileAttributesW(direct.c_str()); + if (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) return direct; + const auto failure = GetLastError(); + const bool missing = attributes == INVALID_FILE_ATTRIBUTES && (failure == ERROR_FILE_NOT_FOUND || failure == ERROR_PATH_NOT_FOUND); + if (!missing && std::filesystem::exists(direct, error)) return direct; + for (auto last = relative.end(); last != relative.begin();) { + const auto parent = Child(root, JoinNames(std::vector(relative.begin(), std::prev(last)))); + const auto parentAttributes = GetFileAttributesW(parent.c_str()); + const bool present = parentAttributes != INVALID_FILE_ATTRIBUTES && (parentAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0; + if (!present && !std::filesystem::exists(parent, error)) { --last; continue; } + root = parent; + first = last; + break; + } +#else if (std::filesystem::exists(direct, error)) return direct; - for (auto part = relative.begin(); part != relative.end(); ++part) { +#endif + for (auto part = first; part != relative.end(); ++part) { const auto candidate = Child(root, *part); const auto status = std::filesystem::symlink_status(candidate, error); if (std::filesystem::exists(status) || (error && error != std::errc::no_such_file_or_directory)) { From 211af5dc9e69a26ad5cc06e8ccec309f22658eb9 Mon Sep 17 00:00:00 2001 From: Evgeniy Kazarin Date: Sun, 18 Oct 2026 04:53:14 -0400 Subject: [PATCH 2/4] chore: record performance-series PR metadata Complete the publication checklist and series cross-links for #7467. No source or test changes. From 87a486fb301dc2601becaf30ccdfb2eed3570f47 Mon Sep 17 00:00:00 2001 From: Evgeniy Kazarin Date: Sun, 18 Oct 2026 09:14:04 -0400 Subject: [PATCH 3/4] fix(libc): preserve lookup in case-sensitive Windows directories --- core/libs/prx/libc/src/General.cpp | 16 ++++++++++--- core/libs/tests/GuestFilesystem.cpp | 37 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/core/libs/prx/libc/src/General.cpp b/core/libs/prx/libc/src/General.cpp index f15ac49ac95d..5d48f36f1ec7 100644 --- a/core/libs/prx/libc/src/General.cpp +++ b/core/libs/prx/libc/src/General.cpp @@ -86,6 +86,17 @@ struct NameMatch { }; #ifdef _WIN32 +bool CaseInsensitiveDirectoryWindows(const std::filesystem::path& directory) { + const auto handle = CreateFileW(directory.c_str(), FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (handle == INVALID_HANDLE_VALUE) return false; + const std::unique_ptr owner(handle, &CloseHandle); + struct { ULONG flags; } information{}; + constexpr auto caseSensitiveInfo = static_cast(23); + return GetFileInformationByHandleEx(handle, caseSensitiveInfo, &information, sizeof(information)) && + (information.flags & FILE_CS_FLAG_CASE_SENSITIVE_DIR) == 0; +} + std::error_code MatchNamesWindows(const std::filesystem::path& directory, std::span names) { for (auto& name : names) { const auto pattern = directory / name.name; @@ -112,8 +123,8 @@ std::error_code MatchNamesWindows(const std::filesystem::path& directory, std::s std::error_code MatchNames(const std::filesystem::path& directory, std::span names) { #ifdef _WIN32 - return MatchNamesWindows(directory, names); -#else + if (CaseInsensitiveDirectoryWindows(directory)) return MatchNamesWindows(directory, names); +#endif std::error_code error; std::filesystem::directory_iterator entry(directory, error), end; for (; !error && entry != end; entry.increment(error)) { @@ -125,7 +136,6 @@ std::error_code MatchNames(const std::filesystem::path& directory, std::span(23); + const bool enabled = SetFileInformationByHandle(handle, caseSensitiveInfo, &information, sizeof(information)); + const auto error = GetLastError(); + CloseHandle(handle); + if (!enabled && (error == ERROR_NOT_SUPPORTED || error == ERROR_INVALID_PARAMETER || error == ERROR_ACCESS_DENIED)) { + std::printf("case-sensitive host directory unavailable: %lu\n", error); + std::filesystem::remove(root); + return; + } + Require(enabled); + { std::ofstream file(root / "File.txt"); file << "payload"; } + Require(std::filesystem::create_directory(root / "Sub")); + Require(std::filesystem::create_directory(root / "Both")); + Require(std::filesystem::create_directory(root / "both")); + { std::ofstream file(root / "libCase.prx.guest.prx"); file << "module"; } + const auto host = root.string(); + AddPathAlias_nid_no_patch("/sensitive-host", host.c_str()); + Require(ResolvePath_nid_no_patch("/sensitive-host/file.txt") == root / "File.txt"); + Require(ResolvePath_nid_no_patch("/sensitive-host/sub") == root / "Sub"); + Require(ResolvePathOrRelinkedModule_nid_no_patch("/sensitive-host/libcase.prx") == root / "libCase.prx.guest.prx"); + bool ambiguous = false; + try { ResolvePath_nid_no_patch("/sensitive-host/BOTH/file.txt"); } + catch (const std::runtime_error& failure) { ambiguous = std::strstr(failure.what(), "Ambiguous case-insensitive guest path") != nullptr; } + Require(ambiguous); + RemovePathAlias_nid_no_patch("/sensitive-host"); + std::filesystem::remove_all(root); +} + static std::filesystem::path ExtendedPath(const std::filesystem::path& path) { const auto& native = path.native(); if (native.starts_with(L"\\\\?\\") || native.starts_with(L"\\\\.\\")) return path; @@ -343,6 +379,7 @@ int main() { TestRelinkedModuleNames(); TestRelinkedModuleNameCase(); #ifdef _WIN32 + TestCaseSensitiveHostDirectory(); TestLongHostPathStat(); #endif #ifdef __linux__ From 5a1590c9f8eefc50d7080f26fae3b8ed07ff99bc Mon Sep 17 00:00:00 2001 From: Evgeniy Kazarin Date: Sun, 18 Oct 2026 13:15:04 -0400 Subject: [PATCH 4/4] fix(libc): resolve the final Windows path component --- core/libs/prx/libc/src/General.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/libs/prx/libc/src/General.cpp b/core/libs/prx/libc/src/General.cpp index 5d48f36f1ec7..90c0cd50883e 100644 --- a/core/libs/prx/libc/src/General.cpp +++ b/core/libs/prx/libc/src/General.cpp @@ -193,7 +193,7 @@ std::filesystem::path ResolveHostPath(std::filesystem::path root, const std::vec const bool present = parentAttributes != INVALID_FILE_ATTRIBUTES && (parentAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0; if (!present && !std::filesystem::exists(parent, error)) { --last; continue; } root = parent; - first = last; + first = std::prev(last); break; } #else