Skip to content

Commit

Permalink
Foundation: adjust _fileExists for NT style paths (#4773)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
compnerd authored Jun 26, 2023
1 parent ba1e4f6 commit 461c9a3
Showing 1 changed file with 27 additions and 21 deletions.
48 changes: 27 additions & 21 deletions Sources/Foundation/FileManager+Win32.swift
Original file line number Diff line number Diff line change
Expand Up @@ -742,27 +742,33 @@ extension FileManager {
}

internal func _fileExists(atPath path: String, isDirectory: UnsafeMutablePointer<ObjCBool>?) -> Bool {
var faAttributes: WIN32_FILE_ATTRIBUTE_DATA = WIN32_FILE_ATTRIBUTE_DATA()
do { faAttributes = try windowsFileAttributes(atPath: path) } catch { return false }
if faAttributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT {
let handle: HANDLE = (try? FileManager.default._fileSystemRepresentation(withPath: path) {
CreateFileW($0, 0, FILE_SHARE_READ, nil, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, nil)
}) ?? INVALID_HANDLE_VALUE
if handle == INVALID_HANDLE_VALUE { return false }
defer { CloseHandle(handle) }

if let isDirectory = isDirectory {
var info: BY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION()
GetFileInformationByHandle(handle, &info)
isDirectory.pointee = ObjCBool(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY)
}
} else {
if let isDirectory = isDirectory {
isDirectory.pointee = ObjCBool(faAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY)
}
}
return true
return (try? withNTPathRepresentation(of: path) {
var faAttributes: WIN32_FILE_ATTRIBUTE_DATA = .init()
guard GetFileAttributesExW($0, GetFileExInfoStandard, &faAttributes) else {
return false
}

var dwFileAttributes = faAttributes.dwFileAttributes
if dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT {
// We use the `CreateFileW` here to ensure that the destination
// of the reparse point exists. The previous check would only
// ensure that the reparse point exists, not the destination of
// it.
let hFile: HANDLE = CreateFileW($0, 0, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nil)
if hFile == INVALID_HANDLE_VALUE { return false }
defer { CloseHandle(hFile) }

var info: BY_HANDLE_FILE_INFORMATION = .init()
GetFileInformationByHandle(hFile, &info)
dwFileAttributes = info.dwFileAttributes
}

if let isDirectory {
isDirectory.pointee = ObjCBool(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY)
}

return true
}) ?? false
}


Expand Down

0 comments on commit 461c9a3

Please sign in to comment.