Skip to content

Commit

Permalink
Foundation: support long file paths for FileHandle on Windows
Browse files Browse the repository at this point in the history
When constructing a `FileHandle` using a path, ensure that we use the NT
file path representation on Windows.  This allows us to access files
that may have greater than `MAX_PATH` length.
  • Loading branch information
compnerd committed Jun 18, 2023
1 parent 819299f commit 9b1d17f
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 6 deletions.
10 changes: 5 additions & 5 deletions Sources/Foundation/FileHandle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -432,12 +432,12 @@ open class FileHandle : NSObject {
}

internal convenience init?(path: String, flags: Int32, createMode: Int) {
guard let fd: Int32 = try? FileManager.default._fileSystemRepresentation(withPath: path, {
_CFOpenFileWithMode($0, flags, mode_t(createMode))
}), fd > 0 else { return nil }
guard let fd: CInt = try? withNTPathRepresentation(of: path, {
_CFOpenFileWithMode($0, flags, mode_t(createMode))
}), fd > 0 else { return nil }

self.init(fileDescriptor: fd, closeOnDealloc: true)
if self._handle == INVALID_HANDLE_VALUE { return nil }
self.init(fileDescriptor: fd, closeOnDealloc: true)
if self._handle == INVALID_HANDLE_VALUE { return nil }
}
#else
public init(fileDescriptor fd: Int32, closeOnDealloc closeopt: Bool) {
Expand Down
5 changes: 4 additions & 1 deletion Sources/Foundation/FileManager+Win32.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extension URL {
}


private func withNTPathRepresentation<Result>(of path: String, _ body: (UnsafePointer<WCHAR>) throws -> Result) throws -> Result {
internal func withNTPathRepresentation<Result>(of path: String, _ body: (UnsafePointer<WCHAR>) throws -> Result) throws -> Result {
guard !path.isEmpty else {
throw CocoaError.error(.fileReadInvalidFileName, userInfo: [NSFilePathErrorKey:path])
}
Expand Down Expand Up @@ -72,6 +72,9 @@ private func withNTPathRepresentation<Result>(of path: String, _ body: (UnsafePo
_ = GetFullPathNameW(pwszPath, DWORD($0.count), $0.baseAddress, nil)
return String(decodingCString: $0.baseAddress!, as: UTF16.self)
}
guard !path.hasPrefix(#"\\"#) else {
return try path.withCString(encodedAs: UTF16.self, body)
}
return try #"\\?\\#(path)"#.withCString(encodedAs: UTF16.self, body)
}
}
Expand Down

0 comments on commit 9b1d17f

Please sign in to comment.