Skip to content

Commit bfa5415

Browse files
committed
Foundation: adjust _fileExists for NT style paths
Adjust the `_fileExists` implementation in `FileManager` for Windows to use NT style paths to exceed path limits of `PATH_MAX` and address the full paths lengths supported by Windows NT.
1 parent ba1e4f6 commit bfa5415

File tree

1 file changed

+29
-21
lines changed

1 file changed

+29
-21
lines changed

Diff for: Sources/Foundation/FileManager+Win32.swift

+29-21
Original file line numberDiff line numberDiff line change
@@ -742,27 +742,35 @@ extension FileManager {
742742
}
743743

744744
internal func _fileExists(atPath path: String, isDirectory: UnsafeMutablePointer<ObjCBool>?) -> Bool {
745-
var faAttributes: WIN32_FILE_ATTRIBUTE_DATA = WIN32_FILE_ATTRIBUTE_DATA()
746-
do { faAttributes = try windowsFileAttributes(atPath: path) } catch { return false }
747-
if faAttributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT {
748-
let handle: HANDLE = (try? FileManager.default._fileSystemRepresentation(withPath: path) {
749-
CreateFileW($0, 0, FILE_SHARE_READ, nil, OPEN_EXISTING,
750-
FILE_FLAG_BACKUP_SEMANTICS, nil)
751-
}) ?? INVALID_HANDLE_VALUE
752-
if handle == INVALID_HANDLE_VALUE { return false }
753-
defer { CloseHandle(handle) }
754-
755-
if let isDirectory = isDirectory {
756-
var info: BY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION()
757-
GetFileInformationByHandle(handle, &info)
758-
isDirectory.pointee = ObjCBool(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY)
759-
}
760-
} else {
761-
if let isDirectory = isDirectory {
762-
isDirectory.pointee = ObjCBool(faAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY)
763-
}
764-
}
765-
return true
745+
return (try? withNTPathRepresentation(of: path) {
746+
var faAttributes: WIN32_FILE_ATTRIBUTE_DATA = .init()
747+
guard GetFileAttributesExW($0, GetFileExInfoStandard, &faAttributes) else {
748+
return false
749+
}
750+
751+
if dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT {
752+
// We use the `CreateFileW` here to ensure that the destination
753+
// of the reparse point exists. The previous check would only
754+
// ensure that the reparse point exists, not the destination of
755+
// it.
756+
let hFile: HANDLE = CreateFileW($0, 0, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nil)
757+
if hFile == INVALID_HANDLE_VALUE { return false }
758+
defer { CloseHandle(hFile) }
759+
760+
if let isDirectory {
761+
var dwFileAttributes = faAttributes.dwFileAttributes
762+
if dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT {
763+
var info: BY_HANDLE_FILE_INFORMATION = .init()
764+
GetFileInformationByHandle(hFile, &info)
765+
dwFileAttributes = info.dwFileAttributes
766+
}
767+
768+
isDirectory.pointee = ObjCBool(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY)
769+
}
770+
}
771+
772+
return true
773+
}) ?? false
766774
}
767775

768776

0 commit comments

Comments
 (0)