@@ -171,7 +171,35 @@ open class FileManager : NSObject {
171
171
}
172
172
}
173
173
}
174
-
174
+
175
+ private func _contentsOfDir( atPath path: String , _ closure: ( String , Int32 ) throws -> ( ) ) throws {
176
+ let fsRep = fileSystemRepresentation ( withPath: path)
177
+ defer { fsRep. deallocate ( ) }
178
+
179
+ guard let dir = opendir ( fsRep) else {
180
+ throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileReadNoSuchFile. rawValue, userInfo: [ NSFilePathErrorKey: path] )
181
+ }
182
+ defer { closedir ( dir) }
183
+
184
+ var entry = dirent ( )
185
+ var result : UnsafeMutablePointer < dirent > ? = nil
186
+
187
+ while readdir_r ( dir, & entry, & result) == 0 {
188
+ guard result != nil else {
189
+ return
190
+ }
191
+ let length = Int ( _direntNameLength ( & entry) )
192
+ let entryName = withUnsafePointer ( to: & entry. d_name) { ( ptr) -> String in
193
+ let namePtr = UnsafeRawPointer ( ptr) . assumingMemoryBound ( to: CChar . self)
194
+ return string ( withFileSystemRepresentation: namePtr, length: length)
195
+ }
196
+ if entryName != " . " && entryName != " .. " {
197
+ let entryType = Int32 ( entry. d_type)
198
+ try closure ( entryName, entryType)
199
+ }
200
+ }
201
+ }
202
+
175
203
/**
176
204
Performs a shallow search of the specified directory and returns the paths of any contained items.
177
205
@@ -186,28 +214,11 @@ open class FileManager : NSObject {
186
214
- Returns: An array of String each of which identifies a file, directory, or symbolic link contained in `path`. The order of the files returned is undefined.
187
215
*/
188
216
open func contentsOfDirectory( atPath path: String ) throws -> [ String ] {
189
- var contents : [ String ] = [ String] ( )
190
-
191
- let dir = opendir ( path)
192
-
193
- if dir == nil {
194
- throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileReadNoSuchFile. rawValue, userInfo: [ NSFilePathErrorKey: path] )
195
- }
196
-
197
- defer {
198
- closedir ( dir!)
199
- }
217
+ var contents : [ String ] = [ ]
200
218
201
- while let entry = readdir ( dir!) {
202
- let entryName = withUnsafePointer ( to: & entry. pointee. d_name) {
203
- String ( cString: UnsafeRawPointer ( $0) . assumingMemoryBound ( to: CChar . self) )
204
- }
205
- // TODO: `entryName` should be limited in length to `entry.memory.d_namlen`.
206
- if entryName != " . " && entryName != " .. " {
207
- contents. append ( entryName)
208
- }
209
- }
210
-
219
+ try _contentsOfDir ( atPath: path, { ( entryName, entryType) throws in
220
+ contents. append ( entryName)
221
+ } )
211
222
return contents
212
223
}
213
224
@@ -225,48 +236,16 @@ open class FileManager : NSObject {
225
236
- Returns: An array of NSString objects, each of which contains the path of an item in the directory specified by path. If path is a symbolic link, this method traverses the link. This method returns nil if it cannot retrieve the device of the linked-to file.
226
237
*/
227
238
open func subpathsOfDirectory( atPath path: String ) throws -> [ String ] {
228
- var contents : [ String ] = [ String] ( )
229
-
230
- let dir = opendir ( path)
231
-
232
- if dir == nil {
233
- throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileReadNoSuchFile. rawValue, userInfo: [ NSFilePathErrorKey: path] )
234
- }
235
-
236
- defer {
237
- closedir ( dir!)
238
- }
239
-
240
- var entry = readdir ( dir!)
241
-
242
- while entry != nil {
243
- let entryName = withUnsafePointer ( to: & entry!. pointee. d_name) {
244
- String ( cString: UnsafeRawPointer ( $0) . assumingMemoryBound ( to: CChar . self) )
245
- }
246
- // TODO: `entryName` should be limited in length to `entry.memory.d_namlen`.
247
- if entryName != " . " && entryName != " .. " {
248
- contents. append ( entryName)
249
-
250
- let entryType = withUnsafePointer ( to: & entry!. pointee. d_type) { ( ptr) -> Int32 in
251
- return Int32 ( ptr. pointee)
252
- }
253
- #if os(OSX) || os(iOS)
254
- let tempEntryType = entryType
255
- #elseif os(Linux) || os(Android) || CYGWIN
256
- let tempEntryType = Int32 ( entryType)
257
- #endif
239
+ var contents : [ String ] = [ ]
258
240
259
- if tempEntryType == Int32 ( DT_DIR ) {
260
- let subPath : String = path + " / " + entryName
261
-
262
- let entries = try subpathsOfDirectory ( atPath : subPath )
263
- contents . append ( contentsOf : entries . map ( { file in " \( entryName ) / \( file ) " } ) )
264
- }
241
+ try _contentsOfDir ( atPath : path , { ( entryName , entryType ) throws in
242
+ contents . append ( entryName)
243
+ if entryType == Int32 ( DT_DIR ) {
244
+ let subPath : String = path + " / " + entryName
245
+ let entries = try subpathsOfDirectory ( atPath : subPath )
246
+ contents . append ( contentsOf : entries . map ( { file in " \( entryName ) / \( file ) " } ) )
265
247
}
266
-
267
- entry = readdir ( dir!)
268
- }
269
-
248
+ } )
270
249
return contents
271
250
}
272
251
0 commit comments