Skip to content

Commit 27042e9

Browse files
authored
Strip \\?\ prefix from path generated by resolveSymlink (#485)
This aligns the implementation of resolveSymlinks with that of Foundation.String._resolvingSymlinksInPath, which received this canonicalization fix in swiftlang/swift-foundation#639.
1 parent 79f5ae3 commit 27042e9

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

Diff for: Sources/TSCBasic/PathShims.swift

+11-5
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,27 @@ import Foundation
2424
public func resolveSymlinks(_ path: AbsolutePath) throws -> AbsolutePath {
2525
#if os(Windows)
2626
let handle: HANDLE = path.pathString.withCString(encodedAs: UTF16.self) {
27-
CreateFileW($0, GENERIC_READ, DWORD(FILE_SHARE_READ), nil,
27+
CreateFileW($0, GENERIC_READ, DWORD(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), nil,
2828
DWORD(OPEN_EXISTING), DWORD(FILE_FLAG_BACKUP_SEMANTICS), nil)
2929
}
3030
if handle == INVALID_HANDLE_VALUE { return path }
3131
defer { CloseHandle(handle) }
3232

3333
let dwLength: DWORD =
34-
GetFinalPathNameByHandleW(handle, nil, 0, DWORD(FILE_NAME_NORMALIZED))
34+
GetFinalPathNameByHandleW(handle, nil, 0, DWORD(VOLUME_NAME_DOS))
3535
return try withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) {
3636
guard GetFinalPathNameByHandleW(handle, $0.baseAddress!, DWORD($0.count),
37-
DWORD(FILE_NAME_NORMALIZED)) == dwLength - 1 else {
37+
DWORD(VOLUME_NAME_DOS)) == dwLength - 1 else {
3838
throw FileSystemError(.unknownOSError, path)
3939
}
40-
let path = String(decodingCString: $0.baseAddress!, as: UTF16.self)
41-
return try AbsolutePath(path)
40+
let pathBaseAddress: UnsafePointer<WCHAR>
41+
if Array($0.prefix(4)) == Array(#"\\?\"#.utf16) {
42+
// When using `VOLUME_NAME_DOS`, the returned path uses `\\?\`.
43+
pathBaseAddress = UnsafePointer($0.baseAddress!.advanced(by: 4))
44+
} else {
45+
pathBaseAddress = UnsafePointer($0.baseAddress!)
46+
}
47+
return try AbsolutePath(String(decodingCString: pathBaseAddress, as: UTF16.self))
4248
}
4349
#else
4450
let pathStr = path.pathString

0 commit comments

Comments
 (0)