Skip to content

Commit 9b1d17f

Browse files
committed
Foundation: support long file paths for FileHandle on Windows
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.
1 parent 819299f commit 9b1d17f

File tree

2 files changed

+9
-6
lines changed

2 files changed

+9
-6
lines changed

Sources/Foundation/FileHandle.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -432,12 +432,12 @@ open class FileHandle : NSObject {
432432
}
433433

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

439-
self.init(fileDescriptor: fd, closeOnDealloc: true)
440-
if self._handle == INVALID_HANDLE_VALUE { return nil }
439+
self.init(fileDescriptor: fd, closeOnDealloc: true)
440+
if self._handle == INVALID_HANDLE_VALUE { return nil }
441441
}
442442
#else
443443
public init(fileDescriptor fd: Int32, closeOnDealloc closeopt: Bool) {

Sources/Foundation/FileManager+Win32.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extension URL {
3030
}
3131

3232

33-
private func withNTPathRepresentation<Result>(of path: String, _ body: (UnsafePointer<WCHAR>) throws -> Result) throws -> Result {
33+
internal func withNTPathRepresentation<Result>(of path: String, _ body: (UnsafePointer<WCHAR>) throws -> Result) throws -> Result {
3434
guard !path.isEmpty else {
3535
throw CocoaError.error(.fileReadInvalidFileName, userInfo: [NSFilePathErrorKey:path])
3636
}
@@ -72,6 +72,9 @@ private func withNTPathRepresentation<Result>(of path: String, _ body: (UnsafePo
7272
_ = GetFullPathNameW(pwszPath, DWORD($0.count), $0.baseAddress, nil)
7373
return String(decodingCString: $0.baseAddress!, as: UTF16.self)
7474
}
75+
guard !path.hasPrefix(#"\\"#) else {
76+
return try path.withCString(encodedAs: UTF16.self, body)
77+
}
7578
return try #"\\?\\#(path)"#.withCString(encodedAs: UTF16.self, body)
7679
}
7780
}

0 commit comments

Comments
 (0)