Skip to content

Commit 66ed508

Browse files
authored
Merge pull request #2914 from compnerd/handle-with-care
Foundation: expose `_handle` from `FileHandle` on Windows
2 parents fc09501 + d615b83 commit 66ed508

File tree

2 files changed

+43
-47
lines changed

2 files changed

+43
-47
lines changed

Sources/Foundation/FileHandle.swift

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,23 +49,19 @@ extension NSError {
4949

5050
open class FileHandle : NSObject {
5151
#if os(Windows)
52-
private var _handle: HANDLE
53-
54-
internal var handle: HANDLE {
55-
return _handle
56-
}
52+
public private(set) var _handle: HANDLE
5753

5854
@available(Windows, unavailable, message: "Cannot perform non-owning handle to fd conversion")
5955
open var fileDescriptor: Int32 {
6056
NSUnsupported()
6157
}
6258

6359
private func _checkFileHandle() {
64-
precondition(_handle != INVALID_HANDLE_VALUE, "Invalid file handle")
60+
precondition(self._handle != INVALID_HANDLE_VALUE, "Invalid file handle")
6561
}
6662

6763
internal var _isPlatformHandleValid: Bool {
68-
return _handle != INVALID_HANDLE_VALUE
64+
return self._handle != INVALID_HANDLE_VALUE
6965
}
7066
#else
7167
private var _fd: Int32
@@ -120,7 +116,7 @@ open class FileHandle : NSObject {
120116
// Closing the file descriptor while Dispatch is monitoring it leads to undefined behavior; guard against that.
121117
#if os(Windows)
122118
var dupHandle: HANDLE?
123-
if !DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &dupHandle,
119+
if !DuplicateHandle(GetCurrentProcess(), self._handle, GetCurrentProcess(), &dupHandle,
124120
/*dwDesiredAccess:*/0, /*bInheritHandle:*/true, DWORD(DUPLICATE_SAME_ACCESS)) {
125121
fatalError("DuplicateHandleFailed: \(GetLastError())")
126122
}
@@ -228,15 +224,15 @@ open class FileHandle : NSObject {
228224
return NSData.NSDataReadResult(bytes: nil, length: 0, deallocator: nil)
229225
}
230226

231-
if GetFileType(_handle) == FILE_TYPE_DISK {
227+
if GetFileType(self._handle) == FILE_TYPE_DISK {
232228
var fiFileInfo: BY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION()
233-
if !GetFileInformationByHandle(_handle, &fiFileInfo) {
229+
if !GetFileInformationByHandle(self._handle, &fiFileInfo) {
234230
throw _NSErrorWithWindowsError(GetLastError(), reading: true)
235231
}
236232

237233
if options.contains(.alwaysMapped) {
238234
let hMapping: HANDLE =
239-
CreateFileMappingA(_handle, nil, DWORD(PAGE_READONLY), 0, 0, nil)
235+
CreateFileMappingA(self._handle, nil, DWORD(PAGE_READONLY), 0, 0, nil)
240236
if hMapping == HANDLE(bitPattern: 0) {
241237
fatalError("CreateFileMappingA failed")
242238
}
@@ -272,7 +268,7 @@ open class FileHandle : NSObject {
272268
}
273269

274270
var BytesRead: DWORD = 0
275-
if !ReadFile(_handle, buffer.advanced(by: total), BytesToRead, &BytesRead, nil) {
271+
if !ReadFile(self._handle, buffer.advanced(by: total), BytesToRead, &BytesRead, nil) {
276272
let err = GetLastError()
277273
if err == ERROR_BROKEN_PIPE {
278274
break
@@ -370,7 +366,7 @@ open class FileHandle : NSObject {
370366
#if os(Windows)
371367
var BytesRead: DWORD = 0
372368
let BytesToRead: DWORD = DWORD(length)
373-
if !ReadFile(_handle, buffer, BytesToRead, &BytesRead, nil) {
369+
if !ReadFile(self._handle, buffer, BytesToRead, &BytesRead, nil) {
374370
throw _NSErrorWithWindowsError(GetLastError(), reading: true)
375371
}
376372
return Int(BytesRead)
@@ -388,7 +384,7 @@ open class FileHandle : NSObject {
388384
var bytesRemaining = length
389385
while bytesRemaining > 0 {
390386
var bytesWritten: DWORD = 0
391-
if !WriteFile(handle, buf.advanced(by: length - bytesRemaining), DWORD(bytesRemaining), &bytesWritten, nil) {
387+
if !WriteFile(self._handle, buf.advanced(by: length - bytesRemaining), DWORD(bytesRemaining), &bytesWritten, nil) {
392388
throw _NSErrorWithWindowsError(GetLastError(), reading: false)
393389
}
394390
if bytesWritten == 0 {
@@ -413,7 +409,7 @@ open class FileHandle : NSObject {
413409

414410
#if os(Windows)
415411
internal init(handle: HANDLE, closeOnDealloc closeopt: Bool) {
416-
_handle = handle
412+
self._handle = handle
417413
_closeOnDealloc = closeopt
418414
}
419415

@@ -424,10 +420,10 @@ open class FileHandle : NSObject {
424420
fatalError("DuplicateHandle() failed: \(GetLastError())")
425421
}
426422
_close(fd)
427-
_handle = handle!
423+
self._handle = handle!
428424
_closeOnDealloc = true
429425
} else {
430-
_handle = HANDLE(bitPattern: _get_osfhandle(fd))!
426+
self._handle = HANDLE(bitPattern: _get_osfhandle(fd))!
431427
_closeOnDealloc = false
432428
}
433429
}
@@ -443,7 +439,7 @@ open class FileHandle : NSObject {
443439
}), fd > 0 else { return nil }
444440

445441
self.init(fileDescriptor: fd, closeOnDealloc: true)
446-
if _handle == INVALID_HANDLE_VALUE { return nil }
442+
if self._handle == INVALID_HANDLE_VALUE { return nil }
447443
}
448444
#else
449445
public init(fileDescriptor fd: Int32, closeOnDealloc closeopt: Bool) {
@@ -525,7 +521,7 @@ open class FileHandle : NSObject {
525521

526522
#if os(Windows)
527523
var liPointer: LARGE_INTEGER = LARGE_INTEGER(QuadPart: 0)
528-
guard SetFilePointerEx(_handle, LARGE_INTEGER(QuadPart: 0), &liPointer, DWORD(FILE_CURRENT)) else {
524+
guard SetFilePointerEx(self._handle, LARGE_INTEGER(QuadPart: 0), &liPointer, DWORD(FILE_CURRENT)) else {
529525
throw _NSErrorWithWindowsError(GetLastError(), reading: true)
530526
}
531527
return UInt64(liPointer.QuadPart)
@@ -545,7 +541,7 @@ open class FileHandle : NSObject {
545541

546542
#if os(Windows)
547543
var liPointer: LARGE_INTEGER = LARGE_INTEGER(QuadPart: 0)
548-
guard SetFilePointerEx(_handle, LARGE_INTEGER(QuadPart: 0), &liPointer, DWORD(FILE_END)) else {
544+
guard SetFilePointerEx(self._handle, LARGE_INTEGER(QuadPart: 0), &liPointer, DWORD(FILE_END)) else {
549545
throw _NSErrorWithWindowsError(GetLastError(), reading: true)
550546
}
551547
return UInt64(liPointer.QuadPart)
@@ -563,7 +559,7 @@ open class FileHandle : NSObject {
563559
guard _isPlatformHandleValid else { throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadUnknown.rawValue) }
564560

565561
#if os(Windows)
566-
guard SetFilePointerEx(_handle, LARGE_INTEGER(QuadPart: LONGLONG(offset)), nil, DWORD(FILE_BEGIN)) else {
562+
guard SetFilePointerEx(self._handle, LARGE_INTEGER(QuadPart: LONGLONG(offset)), nil, DWORD(FILE_BEGIN)) else {
567563
throw _NSErrorWithWindowsError(GetLastError(), reading: true)
568564
}
569565
#else
@@ -578,10 +574,10 @@ open class FileHandle : NSObject {
578574
guard _isPlatformHandleValid else { throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileWriteUnknown.rawValue) }
579575

580576
#if os(Windows)
581-
guard SetFilePointerEx(_handle, LARGE_INTEGER(QuadPart: LONGLONG(offset)), nil, DWORD(FILE_BEGIN)) else {
577+
guard SetFilePointerEx(self._handle, LARGE_INTEGER(QuadPart: LONGLONG(offset)), nil, DWORD(FILE_BEGIN)) else {
582578
throw _NSErrorWithWindowsError(GetLastError(), reading: false)
583579
}
584-
guard SetEndOfFile(_handle) else {
580+
guard SetEndOfFile(self._handle) else {
585581
throw _NSErrorWithWindowsError(GetLastError(), reading: false)
586582
}
587583
#else
@@ -595,7 +591,7 @@ open class FileHandle : NSObject {
595591
guard self != FileHandle._nulldeviceFileHandle else { return }
596592

597593
#if os(Windows)
598-
guard FlushFileBuffers(_handle) else {
594+
guard FlushFileBuffers(self._handle) else {
599595
throw _NSErrorWithWindowsError(GetLastError(), reading: false)
600596
}
601597
#else
@@ -638,10 +634,10 @@ open class FileHandle : NSObject {
638634
privateAsyncVariablesLock.unlock()
639635

640636
#if os(Windows)
641-
guard CloseHandle(_handle) else {
637+
guard CloseHandle(self._handle) else {
642638
throw _NSErrorWithWindowsError(GetLastError(), reading: true)
643639
}
644-
_handle = INVALID_HANDLE_VALUE
640+
self._handle = INVALID_HANDLE_VALUE
645641
#else
646642
guard _close(_fd) >= 0 else {
647643
throw _NSErrorWithErrno(errno, reading: true)
@@ -864,7 +860,7 @@ extension FileHandle {
864860
var translatedError = error
865861
if error == ERROR_ACCESS_DENIED {
866862
var fileInfo = BY_HANDLE_FILE_INFORMATION()
867-
GetFileInformationByHandle(self.handle, &fileInfo)
863+
GetFileInformationByHandle(self._handle, &fileInfo)
868864
if fileInfo.dwFileAttributes & DWORD(FILE_ATTRIBUTE_DIRECTORY) == DWORD(FILE_ATTRIBUTE_DIRECTORY) {
869865
translatedError = ERROR_DIRECTORY_NOT_SUPPORTED
870866
}
@@ -881,7 +877,7 @@ extension FileHandle {
881877
}
882878

883879
#if os(Windows)
884-
DispatchIO.read(fromHandle: handle, maxLength: 1024 * 1024, runningHandlerOn: queue) { (data, error) in
880+
DispatchIO.read(fromHandle: self._handle, maxLength: 1024 * 1024, runningHandlerOn: queue) { (data, error) in
885881
operation(data, error)
886882
}
887883
#else

Sources/Foundation/Process.swift

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ open class Process: NSObject {
504504
var _devNull: FileHandle?
505505
func devNullFd() throws -> HANDLE {
506506
_devNull = try _devNull ?? FileHandle(forUpdating: URL(fileURLWithPath: "NUL", isDirectory: false))
507-
return _devNull!.handle
507+
return _devNull!._handle
508508
}
509509

510510
var modifiedPipes: [(handle: HANDLE, prevValue: DWORD)] = []
@@ -520,55 +520,55 @@ open class Process: NSObject {
520520

521521
switch standardInput {
522522
case let pipe as Pipe:
523-
siStartupInfo.hStdInput = pipe.fileHandleForReading.handle
524-
try deferReset(handle: pipe.fileHandleForWriting.handle)
525-
SetHandleInformation(pipe.fileHandleForWriting.handle, DWORD(HANDLE_FLAG_INHERIT), 0)
523+
siStartupInfo.hStdInput = pipe.fileHandleForReading._handle
524+
try deferReset(handle: pipe.fileHandleForWriting._handle)
525+
SetHandleInformation(pipe.fileHandleForWriting._handle, DWORD(HANDLE_FLAG_INHERIT), 0)
526526

527527
// nil or NullDevice maps to NUL
528528
case let handle as FileHandle where handle === FileHandle._nulldeviceFileHandle: fallthrough
529529
case .none:
530530
siStartupInfo.hStdInput = try devNullFd()
531531

532532
case let handle as FileHandle:
533-
siStartupInfo.hStdInput = handle.handle
534-
try deferReset(handle: handle.handle)
535-
SetHandleInformation(handle.handle, DWORD(HANDLE_FLAG_INHERIT), 1)
533+
siStartupInfo.hStdInput = handle._handle
534+
try deferReset(handle: handle._handle)
535+
SetHandleInformation(handle._handle, DWORD(HANDLE_FLAG_INHERIT), 1)
536536
default: break
537537
}
538538

539539
switch standardOutput {
540540
case let pipe as Pipe:
541-
siStartupInfo.hStdOutput = pipe.fileHandleForWriting.handle
542-
try deferReset(handle: pipe.fileHandleForReading.handle)
543-
SetHandleInformation(pipe.fileHandleForReading.handle, DWORD(HANDLE_FLAG_INHERIT), 0)
541+
siStartupInfo.hStdOutput = pipe.fileHandleForWriting._handle
542+
try deferReset(handle: pipe.fileHandleForReading._handle)
543+
SetHandleInformation(pipe.fileHandleForReading._handle, DWORD(HANDLE_FLAG_INHERIT), 0)
544544

545545
// nil or NullDevice maps to NUL
546546
case let handle as FileHandle where handle === FileHandle._nulldeviceFileHandle: fallthrough
547547
case .none:
548548
siStartupInfo.hStdOutput = try devNullFd()
549549

550550
case let handle as FileHandle:
551-
siStartupInfo.hStdOutput = handle.handle
552-
try deferReset(handle: handle.handle)
553-
SetHandleInformation(handle.handle, DWORD(HANDLE_FLAG_INHERIT), 1)
551+
siStartupInfo.hStdOutput = handle._handle
552+
try deferReset(handle: handle._handle)
553+
SetHandleInformation(handle._handle, DWORD(HANDLE_FLAG_INHERIT), 1)
554554
default: break
555555
}
556556

557557
switch standardError {
558558
case let pipe as Pipe:
559-
siStartupInfo.hStdError = pipe.fileHandleForWriting.handle
560-
try deferReset(handle: pipe.fileHandleForReading.handle)
561-
SetHandleInformation(pipe.fileHandleForReading.handle, DWORD(HANDLE_FLAG_INHERIT), 0)
559+
siStartupInfo.hStdError = pipe.fileHandleForWriting._handle
560+
try deferReset(handle: pipe.fileHandleForReading._handle)
561+
SetHandleInformation(pipe.fileHandleForReading._handle, DWORD(HANDLE_FLAG_INHERIT), 0)
562562

563563
// nil or NullDevice maps to NUL
564564
case let handle as FileHandle where handle === FileHandle._nulldeviceFileHandle: fallthrough
565565
case .none:
566566
siStartupInfo.hStdError = try devNullFd()
567567

568568
case let handle as FileHandle:
569-
siStartupInfo.hStdError = handle.handle
570-
try deferReset(handle: handle.handle)
571-
SetHandleInformation(handle.handle, DWORD(HANDLE_FLAG_INHERIT), 1)
569+
siStartupInfo.hStdError = handle._handle
570+
try deferReset(handle: handle._handle)
571+
SetHandleInformation(handle._handle, DWORD(HANDLE_FLAG_INHERIT), 1)
572572
default: break
573573
}
574574

0 commit comments

Comments
 (0)