Skip to content

Commit 461c9a3

Browse files
authored
Foundation: adjust _fileExists for NT style paths (#4773)
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 461c9a3

File tree

1 file changed

+27
-21
lines changed

1 file changed

+27
-21
lines changed

Sources/Foundation/FileManager+Win32.swift

+27-21
Original file line numberDiff line numberDiff line change
@@ -742,27 +742,33 @@ 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+
var dwFileAttributes = faAttributes.dwFileAttributes
752+
if dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT {
753+
// We use the `CreateFileW` here to ensure that the destination
754+
// of the reparse point exists. The previous check would only
755+
// ensure that the reparse point exists, not the destination of
756+
// it.
757+
let hFile: HANDLE = CreateFileW($0, 0, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nil)
758+
if hFile == INVALID_HANDLE_VALUE { return false }
759+
defer { CloseHandle(hFile) }
760+
761+
var info: BY_HANDLE_FILE_INFORMATION = .init()
762+
GetFileInformationByHandle(hFile, &info)
763+
dwFileAttributes = info.dwFileAttributes
764+
}
765+
766+
if let isDirectory {
767+
isDirectory.pointee = ObjCBool(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY)
768+
}
769+
770+
return true
771+
}) ?? false
766772
}
767773

768774

0 commit comments

Comments
 (0)