From 91a5a2afe464c8b3ff5743ba9a930b79fbe2a765 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 09:07:05 +0000 Subject: [PATCH] Win: handle \\?\UNC\ prefix in realPathFromHandle (PR43204) After r361885, realPathFromHandle() ends up getting called on the working directory on each Clang invocation. This unveiled that the code didn't work for paths on network shares. For example, if one maps the local dir c:\src\tmp to x: net use x: \\localhost\c$\tmp and run e.g. "clang -c foo.cc" in x:\, realPathFromHandle will get \\?\UNC\localhost\c$\src\tmp\ back from GetFinalPathNameByHandleW, and would strip off the initial \\?\ prefix, ending up with a path that doesn't work. This patch makes the prefix stripping a little smarter to handle this case. Differential revision: https://reviews.llvm.org/D67166 llvm-svn: 371035 --- llvm/lib/Support/Windows/Path.inc | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc index dd6ea995d230..c3b13abef5de 100644 --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -371,13 +371,19 @@ static std::error_code realPathFromHandle(HANDLE H, if (std::error_code EC = realPathFromHandle(H, Buffer)) return EC; - const wchar_t *Data = Buffer.data(); + // Strip the \\?\ prefix. We don't want it ending up in output, and such + // paths don't get canonicalized by file APIs. + wchar_t *Data = Buffer.data(); DWORD CountChars = Buffer.size(); - if (CountChars >= 4) { - if (0 == ::memcmp(Data, L"\\\\?\\", 8)) { - CountChars -= 4; - Data += 4; - } + if (CountChars >= 8 && ::memcmp(Data, L"\\\\?\\UNC\\", 16) == 0) { + // Convert \\?\UNC\foo\bar to \\foo\bar + CountChars -= 6; + Data += 6; + Data[0] = '\\'; + } else if (CountChars >= 4 && ::memcmp(Data, L"\\\\?\\", 8) == 0) { + // Convert \\?\c:\foo to c:\foo + CountChars -= 4; + Data += 4; } // Convert the result from UTF-16 to UTF-8.