@@ -137,7 +137,10 @@ open class FileManager : NSObject {
137
137
let modeT = number. uint32Value
138
138
#endif
139
139
#if CAN_IMPORT_MINGWCRT
140
- if chmod ( path, Int32 ( mode_t ( modeT) ) ) != 0 {
140
+ var wcpath = [ UInt16] ( path. utf16)
141
+ wcpath. append ( UInt16 ( 0 ) )
142
+
143
+ if _wchmod ( wcpath, Int32 ( mode_t ( modeT) ) ) != 0 {
141
144
fatalError ( " errno \( errno) " )
142
145
}
143
146
#else
@@ -156,6 +159,10 @@ open class FileManager : NSObject {
156
159
This method replaces createDirectoryAtPath:attributes:
157
160
*/
158
161
open func createDirectory( atPath path: String , withIntermediateDirectories createIntermediates: Bool , attributes: [ FileAttributeKey : Any ] ? = [ : ] ) throws {
162
+ #if CAN_IMPORT_MINGWCRT
163
+ var wcpath = [ UInt16] ( path. utf16)
164
+ wcpath. append ( UInt16 ( 0 ) )
165
+ #endif
159
166
if createIntermediates {
160
167
var isDir : ObjCBool = false
161
168
if !fileExists( atPath: path, isDirectory: & isDir) {
@@ -164,7 +171,7 @@ open class FileManager : NSObject {
164
171
try createDirectory ( atPath: parent, withIntermediateDirectories: true , attributes: attributes)
165
172
}
166
173
#if CAN_IMPORT_MINGWCRT
167
- let mkdir_failed = _mkdir ( path ) != 0
174
+ let mkdir_failed = _wmkdir ( wcpath ) != 0
168
175
#else
169
176
let mkdir_failed = mkdir ( pathh, S_IRWXU | S_IRWXG | S_IRWXO) != 0
170
177
#endif
@@ -180,7 +187,7 @@ open class FileManager : NSObject {
180
187
}
181
188
} else {
182
189
#if CAN_IMPORT_MINGWCRT
183
- let mkdir_failed = _mkdir ( path ) != 0
190
+ let mkdir_failed = _wmkdir ( wcpath ) != 0
184
191
#else
185
192
let mkdir_failed = mkdir ( pathh, S_IRWXU | S_IRWXG | S_IRWXO) != 0
186
193
#endif
@@ -207,14 +214,40 @@ open class FileManager : NSObject {
207
214
*/
208
215
open func contentsOfDirectory( atPath path: String ) throws -> [ String ] {
209
216
var contents : [ String ] = [ String] ( )
210
-
217
+ #if CAN_IMPORT_MINGWCRT
218
+ var wcpath = [ UInt16] ( path. utf16)
219
+ wcpath. append ( UInt16 ( 0 ) )
220
+
221
+ let dir = _wopendir ( wcpath)
222
+ #else
211
223
let dir = opendir ( path)
212
-
224
+ #endif
225
+
213
226
if dir == nil {
214
227
throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileReadNoSuchFile. rawValue, userInfo: [ NSFilePathErrorKey: path] )
215
228
}
216
-
229
+
230
+ #if CAN_IMPORT_MINGWCRT
217
231
defer {
232
+
233
+ _wclosedir ( dir!)
234
+ }
235
+
236
+ while let entry = _wreaddir ( dir!) {
237
+ let entryNameLen = withUnsafePointer ( to: & entry. pointee. d_namlen) {
238
+ UnsafeRawPointer ( $0) . assumingMemoryBound ( to: UInt16 . self) . pointee
239
+ }
240
+ let entryName = withUnsafePointer ( to: & entry. pointee. d_name) {
241
+ String ( utf16CodeUnits: UnsafeRawPointer ( $0) . assumingMemoryBound ( to: UInt16 . self) , count: Int ( entryNameLen) )
242
+ }
243
+
244
+ if entryName != " . " && entryName != " .. " {
245
+ contents. append ( entryName)
246
+ }
247
+ }
248
+ #else
249
+ defer {
250
+
218
251
closedir ( dir!)
219
252
}
220
253
@@ -227,7 +260,7 @@ open class FileManager : NSObject {
227
260
contents. append ( entryName)
228
261
}
229
262
}
230
-
263
+ #endif
231
264
return contents
232
265
}
233
266
@@ -245,31 +278,65 @@ open class FileManager : NSObject {
245
278
- 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.
246
279
*/
247
280
open func subpathsOfDirectory( atPath path: String ) throws -> [ String ] {
281
+ var contents : [ String ] = [ String] ( )
248
282
#if CAN_IMPORT_MINGWCRT
249
- NSUnimplemented ( )
283
+ var wcpath = [ UInt16] ( path. utf16)
284
+ wcpath. append ( UInt16 ( 0 ) )
285
+
286
+ let dir = _wopendir ( wcpath)
250
287
#else
251
- var contents : [ String ] = [ String] ( )
252
288
253
289
let dir = opendir ( path)
290
+ #endif
254
291
255
292
if dir == nil {
256
293
throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileReadNoSuchFile. rawValue, userInfo: [ NSFilePathErrorKey: path] )
257
294
}
258
295
296
+
297
+ #if CAN_IMPORT_MINGWCRT
259
298
defer {
299
+
300
+ _wclosedir ( dir!)
301
+ }
302
+
303
+ var entry = _wreaddir ( dir!)
304
+ #else
305
+ defer {
306
+
260
307
closedir ( dir!)
261
308
}
262
-
309
+
263
310
var entry = readdir ( dir!)
311
+ #endif
264
312
265
313
while entry != nil {
314
+ #if CAN_IMPORT_MINGWCRT
315
+ let entryNameLen = withUnsafePointer ( to: & entry!. pointee. d_namlen) {
316
+ UnsafeRawPointer ( $0) . assumingMemoryBound ( to: UInt16 . self) . pointee
317
+ }
318
+ let entryName = withUnsafePointer ( to: & entry!. pointee. d_name) {
319
+ String ( utf16CodeUnits: UnsafeRawPointer ( $0) . assumingMemoryBound ( to: UInt16 . self) , count: Int ( entryNameLen) )
320
+ }
321
+ #else
266
322
let entryName = withUnsafePointer ( to: & entry!. pointee. d_name) {
267
323
String ( cString: UnsafeRawPointer ( $0) . assumingMemoryBound ( to: CChar . self) )
268
324
}
325
+ #endif
269
326
// TODO: `entryName` should be limited in length to `entry.memory.d_namlen`.
270
327
if entryName != " . " && entryName != " .. " {
271
328
contents. append ( entryName)
272
-
329
+
330
+ #if CAN_IMPORT_MINGWCRT
331
+ let subPath : String = path + " / " + entryName
332
+ var isDir = false
333
+
334
+ if fileExists ( atPath: subPath, isDirectory: & isDir) && isDir {
335
+ print ( " \( subPath) isDir " )
336
+ let entries = try subpathsOfDirectory ( atPath: subPath)
337
+ contents. append ( contentsOf: entries. map ( { file in " \( entryName) / \( file) " } ) )
338
+ }
339
+ #else
273
340
let entryType = withUnsafePointer ( to: & entry!. pointee. d_type) { ( ptr) -> Int32 in
274
341
return Int32 ( ptr. pointee)
275
342
}
@@ -285,13 +352,16 @@ open class FileManager : NSObject {
285
352
let entries = try subpathsOfDirectory ( atPath: subPath)
286
353
contents. append ( contentsOf: entries. map ( { file in " \( entryName) / \( file) " } ) )
287
354
}
355
+ #endif
288
356
}
289
-
357
+ #if CAN_IMPORT_MINGWCRT
358
+ entry = _wreaddir ( dir!)
359
+ #else
290
360
entry = readdir ( dir!)
361
+ #endif
291
362
}
292
363
293
364
return contents
294
- #endif
295
365
}
296
366
297
367
/* attributesOfItemAtPath:error: returns an NSDictionary of key/value pairs containing the attributes of the item (file, directory, symlink, etc.) at the path in question. If this method returns 'nil', an NSError will be returned by reference in the 'error' parameter. This method does not traverse a terminal symlink.
@@ -300,29 +370,46 @@ open class FileManager : NSObject {
300
370
*/
301
371
open func attributesOfItem( atPath path: String ) throws -> [ FileAttributeKey : Any ] {
302
372
#if CAN_IMPORT_MINGWCRT
303
- NSUnimplemented ( )
373
+ var wcpath = [ UInt16] ( path. utf16)
374
+ wcpath. append ( UInt16 ( 0 ) )
375
+
376
+ var s = _stat64 ( )
377
+ guard _wstat64 ( wcpath, & s) == 0 else {
378
+ throw _NSErrorWithErrno ( errno, reading: true , path: path)
379
+ }
304
380
#else
305
381
var s = stat ( )
306
382
guard lstat ( path, & s) == 0 else {
307
383
throw _NSErrorWithErrno ( errno, reading: true , path: path)
308
384
}
385
+ #endif
309
386
var result = [ FileAttributeKey : Any] ( )
310
387
result [ . size] = NSNumber ( value: UInt64 ( s. st_size) )
311
388
312
389
#if os(OSX) || os(iOS)
313
390
let ti = ( TimeInterval ( s. st_mtimespec. tv_sec) - kCFAbsoluteTimeIntervalSince1970) + ( 1.0e-9 * TimeInterval( s. st_mtimespec. tv_nsec) )
314
391
#elseif os(Android)
315
392
let ti = ( TimeInterval ( s. st_mtime) - kCFAbsoluteTimeIntervalSince1970) + ( 1.0e-9 * TimeInterval( s. st_mtime_nsec) )
393
+ #elseif CAN_IMPORT_MINGWCRT
394
+ let ti = ( TimeInterval ( s. st_mtime) - kCFAbsoluteTimeIntervalSince1970)
316
395
#else
317
- let ti = ( TimeInterval ( s. st_mtim . tv_sec) - kCFAbsoluteTimeIntervalSince1970) + ( 1.0e-9 * TimeInterval( s. st_mtim. tv_nsec) )
396
+ let ti = ( TimeInterval ( s. st_mtime . tv_sec) - kCFAbsoluteTimeIntervalSince1970) + ( 1.0e-9 * TimeInterval( s. st_mtim. tv_nsec) )
318
397
#endif
319
398
result [ . modificationDate] = Date ( timeIntervalSinceReferenceDate: ti)
320
399
321
400
result [ . posixPermissions] = NSNumber ( value: UInt64 ( s. st_mode & 0o7777 ) )
322
401
result [ . referenceCount] = NSNumber ( value: UInt64 ( s. st_nlink) )
323
402
result [ . systemNumber] = NSNumber ( value: UInt64 ( s. st_dev) )
324
403
result [ . systemFileNumber] = NSNumber ( value: UInt64 ( s. st_ino) )
325
-
404
+ #if CAN_IMPORT_MINGWCRT
405
+ var type : FileAttributeType
406
+ switch Int32 ( s. st_mode) & S_IFMT {
407
+ case S_IFCHR: type = . typeCharacterSpecial
408
+ case S_IFDIR: type = . typeDirectory
409
+ case S_IFREG: type = . typeRegular
410
+ default : type = . typeUnknown
411
+ }
412
+ #else
326
413
let pwd = getpwuid ( s. st_uid)
327
414
if pwd != nil && pwd!. pointee. pw_name != nil {
328
415
let name = String ( cString: pwd!. pointee. pw_name)
@@ -345,6 +432,7 @@ open class FileManager : NSObject {
345
432
case S_IFSOCK: type = . typeSocket
346
433
default : type = . typeUnknown
347
434
}
435
+ #endif
348
436
result [ . type] = type
349
437
350
438
if type == . typeBlockSpecial || type == . typeCharacterSpecial {
@@ -363,7 +451,7 @@ open class FileManager : NSObject {
363
451
result [ . groupOwnerAccountID] = NSNumber ( value: UInt64 ( s. st_gid) )
364
452
365
453
return result
366
- #endif
454
+
367
455
}
368
456
369
457
/* attributesOfFileSystemForPath:error: returns an NSDictionary of key/value pairs containing the attributes of the filesystem containing the provided path. If this method returns 'nil', an NSError will be returned by reference in the 'error' parameter. This method does not traverse a terminal symlink.
@@ -431,6 +519,16 @@ open class FileManager : NSObject {
431
519
guard !self . fileExists ( atPath: dstPath) else {
432
520
throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileWriteFileExists. rawValue, userInfo: [ NSFilePathErrorKey : NSString ( dstPath) ] )
433
521
}
522
+ #if CAN_IMPORT_MINGWCRT
523
+ var wcSrcPath = [ UInt16] ( srcPath. utf16)
524
+ wcSrcPath. append ( UInt16 ( 0 ) )
525
+ var wcDstPath = [ UInt16] ( dstPath. utf16)
526
+ wcDstPath. append ( UInt16 ( 0 ) )
527
+
528
+ if _wrename ( wcSrcPath, wcDstPath) != 0 {
529
+ throw _NSErrorWithErrno ( errno, reading: false , path: srcPath)
530
+ }
531
+ #else
434
532
if rename ( srcPath, dstPath) != 0 {
435
533
if errno == EXDEV {
436
534
// TODO: Copy and delete.
@@ -439,6 +537,7 @@ open class FileManager : NSObject {
439
537
throw _NSErrorWithErrno ( errno, reading: false , path: srcPath)
440
538
}
441
539
}
540
+ #endif
442
541
}
443
542
444
543
open func linkItem( atPath srcPath: String , toPath dstPath: String ) throws {
@@ -462,7 +561,29 @@ open class FileManager : NSObject {
462
561
463
562
open func removeItem( atPath path: String ) throws {
464
563
#if CAN_IMPORT_MINGWCRT
465
- NSUnimplemented ( )
564
+ var wcpath = [ UInt16] ( path. utf16)
565
+ wcpath. append ( UInt16 ( 0 ) )
566
+
567
+ var s = _stat64 ( )
568
+ guard _wstat64 ( wcpath, & s) == 0 else {
569
+ throw _NSErrorWithErrno ( errno, reading: true , path: path)
570
+ }
571
+
572
+ if ( Int32 ( s. st_mode) & S_IFMT) == S_IFDIR {
573
+ let subpaths = try subpathsOfDirectory ( atPath: path)
574
+ for subpath in subpaths {
575
+ try removeItem ( atPath: path + " / " + subpath)
576
+ }
577
+
578
+ if _wrmdir ( wcpath) != 0 {
579
+ throw _NSErrorWithErrno ( errno, reading: false , path: path)
580
+ }
581
+
582
+ } else {
583
+ if _wunlink ( wcpath) != 0 {
584
+ throw _NSErrorWithErrno ( errno, reading: false , path: path)
585
+ }
586
+ }
466
587
#else
467
588
if rmdir ( path) == 0 {
468
589
return
@@ -554,19 +675,34 @@ open class FileManager : NSObject {
554
675
open var currentDirectoryPath : String {
555
676
#if CAN_IMPORT_MINGWCRT
556
677
let length = Int32 ( _MAX_PATH) + 1
557
- var buf = [ Int8] ( repeating: 0 , count: Int ( length) )
678
+ var buf = [ UInt16] ( repeating: 0 , count: Int ( length) )
679
+
680
+ _wgetcwd ( & buf, length)
681
+
682
+ let result = String ( utf16CodeUnits: buf, count: wcslen ( buf) )
558
683
#else
559
684
let length = Int ( PATH_MAX) + 1
560
685
var buf = [ Int8] ( repeating: 0 , count: length)
561
- #endif
686
+
562
687
getcwd ( & buf, length)
688
+
563
689
let result = self . string ( withFileSystemRepresentation: buf, length: Int ( strlen ( buf) ) )
690
+ #endif
691
+
692
+
564
693
return result
565
694
}
566
695
567
696
@discardableResult
568
697
open func changeCurrentDirectoryPath( _ path: String ) -> Bool {
698
+ #if CAN_IMPORT_MINGWCRT
699
+ var wcpath = [ UInt16] ( path. utf16)
700
+ wcpath. append ( UInt16 ( 0 ) )
701
+
702
+ return _wchdir ( wcpath) == 0
703
+ #else
569
704
return chdir ( path) == 0
705
+ #endif
570
706
}
571
707
572
708
/* The following methods are of limited utility. Attempting to predicate behavior based on the current state of the filesystem or a particular file on the filesystem is encouraging odd behavior in the face of filesystem race conditions. It's far better to attempt an operation (like loading a file or creating a directory) and handle the error gracefully than it is to try to figure out ahead of time whether the operation will succeed.
@@ -577,7 +713,18 @@ open class FileManager : NSObject {
577
713
578
714
open func fileExists( atPath path: String , isDirectory: UnsafeMutablePointer < ObjCBool > ? ) -> Bool {
579
715
#if CAN_IMPORT_MINGWCRT
580
- NSUnimplemented ( )
716
+ var wcpath = [ UInt16] ( path. utf16)
717
+ wcpath. append ( UInt16 ( 0 ) )
718
+ var s = _stat64 ( )
719
+ if _wstat64 ( wcpath, & s) >= 0 {
720
+ if let isDirectory = isDirectory {
721
+ isDirectory. pointee = ( Int32 ( s. st_mode) & S_IFMT) == S_IFDIR
722
+ }
723
+ } else {
724
+ return false
725
+ }
726
+
727
+ return true
581
728
#else
582
729
var s = stat ( )
583
730
if lstat ( path, & s) >= 0 {
0 commit comments