1
1
// This source file is part of the Swift.org open source project
2
2
//
3
- // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
3
+ // Copyright (c) 2014 - 2016, 2018 Apple Inc. and the Swift project authors
4
4
// Licensed under Apache License v2.0 with Runtime Library Exception
5
5
//
6
- // See http ://swift.org/LICENSE.txt for license information
7
- // See http ://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
6
+ // See https ://swift.org/LICENSE.txt for license information
7
+ // See https ://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
8
8
//
9
9
10
10
import CoreFoundation
@@ -16,10 +16,13 @@ import Glibc
16
16
#endif
17
17
18
18
open class FileHandle : NSObject , NSSecureCoding {
19
- internal var _fd : Int32
20
- internal var _closeOnDealloc : Bool
21
- internal var _closed : Bool = false
22
-
19
+ private var _fd : Int32
20
+ private var _closeOnDealloc : Bool
21
+
22
+ open var fileDescriptor : Int32 {
23
+ return _fd
24
+ }
25
+
23
26
open var availableData : Data {
24
27
return _readDataOfLength ( Int . max, untilEOF: false )
25
28
}
@@ -33,10 +36,11 @@ open class FileHandle : NSObject, NSSecureCoding {
33
36
}
34
37
35
38
internal func _readDataOfLength( _ length: Int , untilEOF: Bool ) -> Data {
39
+ precondition ( _fd >= 0 , " Bad file descriptor " )
36
40
var statbuf = stat ( )
37
41
var dynamicBuffer : UnsafeMutableRawPointer ? = nil
38
42
var total = 0
39
- if _closed || fstat ( _fd, & statbuf) < 0 {
43
+ if fstat ( _fd, & statbuf) < 0 {
40
44
fatalError ( " Unable to read file " )
41
45
}
42
46
if statbuf. st_mode & S_IFMT != S_IFREG {
@@ -119,6 +123,7 @@ open class FileHandle : NSObject, NSSecureCoding {
119
123
}
120
124
121
125
open func write( _ data: Data ) {
126
+ precondition ( _fd >= 0 , " Bad file descriptor " )
122
127
data. enumerateBytes ( ) { ( bytes, range, stop) in
123
128
do {
124
129
try NSData . write ( toFileDescriptor: self . _fd, path: nil , buf: UnsafeRawPointer ( bytes. baseAddress!) , length: bytes. count)
@@ -131,40 +136,49 @@ open class FileHandle : NSObject, NSSecureCoding {
131
136
// TODO: Error handling.
132
137
133
138
open var offsetInFile : UInt64 {
139
+ precondition ( _fd >= 0 , " Bad file descriptor " )
134
140
return UInt64 ( lseek ( _fd, 0 , SEEK_CUR) )
135
141
}
136
142
137
143
@discardableResult
138
144
open func seekToEndOfFile( ) -> UInt64 {
145
+ precondition ( _fd >= 0 , " Bad file descriptor " )
139
146
return UInt64 ( lseek ( _fd, 0 , SEEK_END) )
140
147
}
141
148
142
149
open func seek( toFileOffset offset: UInt64 ) {
150
+ precondition ( _fd >= 0 , " Bad file descriptor " )
143
151
lseek ( _fd, off_t ( offset) , SEEK_SET)
144
152
}
145
153
146
154
open func truncateFile( atOffset offset: UInt64 ) {
155
+ precondition ( _fd >= 0 , " Bad file descriptor " )
147
156
if lseek ( _fd, off_t ( offset) , SEEK_SET) == 0 {
148
157
ftruncate ( _fd, off_t ( offset) )
149
158
}
150
159
}
151
160
152
161
open func synchronizeFile( ) {
162
+ precondition ( _fd >= 0 , " Bad file descriptor " )
153
163
fsync ( _fd)
154
164
}
155
165
156
166
open func closeFile( ) {
157
- if !_closed {
167
+ if _fd >= 0 {
158
168
close ( _fd)
159
- _closed = true
169
+ _fd = - 1
160
170
}
161
171
}
162
-
172
+
163
173
public init ( fileDescriptor fd: Int32 , closeOnDealloc closeopt: Bool ) {
164
174
_fd = fd
165
175
_closeOnDealloc = closeopt
166
176
}
167
-
177
+
178
+ public convenience init ( fileDescriptor fd: Int32 ) {
179
+ self . init ( fileDescriptor: fd, closeOnDealloc: false )
180
+ }
181
+
168
182
internal init ? ( path: String , flags: Int32 , createMode: Int ) {
169
183
_fd = _CFOpenFileWithMode ( path, flags, mode_t ( createMode) )
170
184
_closeOnDealloc = true
@@ -175,8 +189,9 @@ open class FileHandle : NSObject, NSSecureCoding {
175
189
}
176
190
177
191
deinit {
178
- if _fd >= 0 && _closeOnDealloc && !_closed {
192
+ if _fd >= 0 && _closeOnDealloc {
179
193
close ( _fd)
194
+ _fd = - 1
180
195
}
181
196
}
182
197
@@ -357,46 +372,32 @@ extension FileHandle {
357
372
}
358
373
}
359
374
360
- extension FileHandle {
361
- public convenience init ( fileDescriptor fd: Int32 ) {
362
- self . init ( fileDescriptor: fd, closeOnDealloc: false )
363
- }
364
-
365
- open var fileDescriptor : Int32 {
366
- return _fd
367
- }
368
- }
369
-
370
375
open class Pipe : NSObject {
371
- private let readHandle : FileHandle
372
- private let writeHandle : FileHandle
373
-
376
+ public let fileHandleForReading : FileHandle
377
+ public let fileHandleForWriting : FileHandle
378
+
374
379
public override init ( ) {
375
380
/// the `pipe` system call creates two `fd` in a malloc'ed area
376
381
var fds = UnsafeMutablePointer< Int32> . allocate( capacity: 2 )
377
382
defer {
378
- free ( fds)
383
+ fds. deallocate ( )
379
384
}
380
385
/// If the operating system prevents us from creating file handles, stop
381
- guard pipe ( fds) == 0 else { fatalError ( " Could not open pipe file handles " ) }
382
-
383
- /// The handles below auto-close when the `NSFileHandle` is deallocated, so we
384
- /// don't need to add a `deinit` to this class
385
-
386
- /// Create the read handle from the first fd in `fds`
387
- self . readHandle = FileHandle ( fileDescriptor: fds. pointee, closeOnDealloc: true )
388
-
389
- /// Advance `fds` by one to create the write handle from the second fd
390
- self . writeHandle = FileHandle ( fileDescriptor: fds. successor ( ) . pointee, closeOnDealloc: true )
391
-
386
+ let ret = pipe ( fds)
387
+ switch ( ret, errno) {
388
+ case ( 0 , _) :
389
+ self . fileHandleForReading = FileHandle ( fileDescriptor: fds. pointee, closeOnDealloc: true )
390
+ self . fileHandleForWriting = FileHandle ( fileDescriptor: fds. successor ( ) . pointee, closeOnDealloc: true )
391
+
392
+ case ( - 1 , EMFILE) , ( - 1 , ENFILE) :
393
+ // Unfortunately this initializer does not throw and isnt failable so this is only
394
+ // way of handling this situation.
395
+ self . fileHandleForReading = FileHandle ( fileDescriptor: - 1 , closeOnDealloc: false )
396
+ self . fileHandleForWriting = FileHandle ( fileDescriptor: - 1 , closeOnDealloc: false )
397
+
398
+ default :
399
+ fatalError ( " Error calling pipe(): \( errno) " )
400
+ }
392
401
super. init ( )
393
402
}
394
-
395
- open var fileHandleForReading : FileHandle {
396
- return self . readHandle
397
- }
398
-
399
- open var fileHandleForWriting : FileHandle {
400
- return self . writeHandle
401
- }
402
403
}
0 commit comments