10
10
import CoreFoundation
11
11
12
12
#if os(Windows)
13
- internal func joinPath( prefix: String , suffix: String ) -> String {
13
+
14
+ internal func joinPath( prefix: String , suffix: String ) throws -> String {
14
15
var pszPath : PWSTR ?
15
- _ = prefix . withCString ( encodedAs : UTF16 . self ) { prefix in
16
- _ = suffix . withCString ( encodedAs : UTF16 . self ) { suffix in
17
- PathAllocCombine ( prefix , suffix , ULONG ( PATHCCH_ALLOW_LONG_PATHS . rawValue ) , & pszPath )
18
- }
16
+ guard S_OK == ( try FileManager . default . _fileSystemRepresentation ( withPath : prefix , andPath : suffix ) {
17
+ PathAllocCombine ( $0 , $1 , ULONG ( PATHCCH_ALLOW_LONG_PATHS . rawValue ) , & pszPath )
18
+ } ) else {
19
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading : false , paths : [ prefix ] )
19
20
}
20
21
21
22
let path : String = String ( decodingCString: pszPath!, as: UTF16 . self)
@@ -177,11 +178,8 @@ extension FileManager {
177
178
UnsafeMutablePointer < SECURITY_ATTRIBUTES > ( & saAttributes)
178
179
179
180
180
- try path. withCString ( encodedAs: UTF16 . self) {
181
- if !CreateDirectoryW( $0, psaAttributes) {
182
- // FIXME(compnerd) pass along path
183
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ path] )
184
- }
181
+ guard try _fileSystemRepresentation ( withPath: path, { CreateDirectoryW ( $0, psaAttributes) } ) else {
182
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ path] )
185
183
}
186
184
if let attr = attributes {
187
185
try self . setAttributes ( attr, ofItemAtPath: path)
@@ -192,7 +190,7 @@ extension FileManager {
192
190
guard path != " " else {
193
191
throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileReadInvalidFileName. rawValue, userInfo: [ NSFilePathErrorKey : NSString ( path) ] )
194
192
}
195
- try ( path + " \\ * " ) . withCString ( encodedAs : UTF16 . self ) {
193
+ try _fileSystemRepresentation ( withPath : path + " \\ * " ) {
196
194
var ffd : WIN32_FIND_DATAW = WIN32_FIND_DATAW ( )
197
195
198
196
let hDirectory : HANDLE = FindFirstFileW ( $0, & ffd)
@@ -221,17 +219,17 @@ extension FileManager {
221
219
contents. append ( entryName)
222
220
if entryType & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY
223
221
&& entryType & FILE_ATTRIBUTE_REPARSE_POINT != FILE_ATTRIBUTE_REPARSE_POINT {
224
- let subPath : String = joinPath ( prefix: path, suffix: entryName)
222
+ let subPath : String = try joinPath ( prefix: path, suffix: entryName)
225
223
let entries = try subpathsOfDirectory ( atPath: subPath)
226
- contents. append ( contentsOf: entries. map { joinPath ( prefix: entryName, suffix: $0) . standardizingPath } )
224
+ contents. append ( contentsOf: try entries. map { try joinPath ( prefix: entryName, suffix: $0) . standardizingPath } )
227
225
}
228
226
} )
229
227
return contents
230
228
}
231
229
232
230
internal func windowsFileAttributes( atPath path: String ) throws -> WIN32_FILE_ATTRIBUTE_DATA {
233
231
var faAttributes : WIN32_FILE_ATTRIBUTE_DATA = WIN32_FILE_ATTRIBUTE_DATA ( )
234
- return try path . withCString ( encodedAs : UTF16 . self ) {
232
+ return try _fileSystemRepresentation ( withPath : path ) {
235
233
if !GetFileAttributesExW( $0, GetFileExInfoStandard, & faAttributes) {
236
234
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path] )
237
235
}
@@ -246,7 +244,7 @@ extension FileManager {
246
244
internal func _attributesOfFileSystem( forPath path: String ) throws -> [ FileAttributeKey : Any ] {
247
245
var result : [ FileAttributeKey : Any ] = [ : ]
248
246
249
- try path . withCString ( encodedAs : UTF16 . self ) {
247
+ try _fileSystemRepresentation ( withPath : path ) {
250
248
let dwLength : DWORD = GetFullPathNameW ( $0, 0 , nil , nil )
251
249
guard dwLength != 0 else {
252
250
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path] )
@@ -303,12 +301,8 @@ extension FileManager {
303
301
}
304
302
}
305
303
306
- try path. withCString ( encodedAs: UTF16 . self) { name in
307
- try destPath. withCString ( encodedAs: UTF16 . self) { dest in
308
- guard CreateSymbolicLinkW ( name, dest, dwFlags) != 0 else {
309
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path, destPath] )
310
- }
311
- }
304
+ guard try _fileSystemRepresentation ( withPath: path, andPath: destPath, { CreateSymbolicLinkW ( $0, $1, dwFlags) != 0 } ) else {
305
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path, destPath] )
312
306
}
313
307
}
314
308
@@ -318,10 +312,14 @@ extension FileManager {
318
312
throw _NSErrorWithWindowsError ( DWORD ( ERROR_BAD_ARGUMENTS) , reading: false )
319
313
}
320
314
321
- let handle = path. withCString ( encodedAs: UTF16 . self) { symlink in
322
- CreateFileW ( symlink, GENERIC_READ, DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
323
- nil , DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS) ,
324
- nil )
315
+ let handle = try _fileSystemRepresentation ( withPath: path) {
316
+ CreateFileW ( $0,
317
+ GENERIC_READ,
318
+ DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
319
+ nil ,
320
+ DWORD ( OPEN_EXISTING) ,
321
+ DWORD ( FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS) ,
322
+ nil )
325
323
}
326
324
327
325
guard handle != INVALID_HANDLE_VALUE else {
@@ -400,16 +398,15 @@ extension FileManager {
400
398
}
401
399
402
400
internal func _canonicalizedPath( toFileAtPath path: String ) throws -> String {
403
- var hFile : HANDLE = INVALID_HANDLE_VALUE
404
- path. withCString ( encodedAs: UTF16 . self) { link in
405
- // BACKUP_SEMANTICS are (confusingly) required in order to receive a
406
- // handle to a directory
407
- hFile = CreateFileW ( link, 0 , DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
408
- nil , DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_BACKUP_SEMANTICS) ,
409
- nil )
401
+ var hFile : HANDLE = try _fileSystemRepresentation ( withPath: path) {
402
+ // BACKUP_SEMANTICS are (confusingly) required in order to receive a
403
+ // handle to a directory
404
+ CreateFileW ( $0, 0 , DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
405
+ nil , DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_BACKUP_SEMANTICS) ,
406
+ nil )
410
407
}
411
408
guard hFile != INVALID_HANDLE_VALUE else {
412
- return try path . withCString ( encodedAs : UTF16 . self ) {
409
+ return try _fileSystemRepresentation ( withPath : path ) {
413
410
var dwLength = GetFullPathNameW ( $0, 0 , nil , nil )
414
411
var szPath = Array < WCHAR > ( repeating: 0 , count: Int ( dwLength + 1 ) )
415
412
dwLength = GetFullPathNameW ( $0, DWORD ( szPath. count) , & szPath, nil )
@@ -429,12 +426,8 @@ extension FileManager {
429
426
}
430
427
431
428
internal func _copyRegularFile( atPath srcPath: String , toPath dstPath: String , variant: String = " Copy " ) throws {
432
- try srcPath. withCString ( encodedAs: UTF16 . self) { src in
433
- try dstPath. withCString ( encodedAs: UTF16 . self) { dst in
434
- if !CopyFileW( src, dst, false ) {
435
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ srcPath, dstPath] )
436
- }
437
- }
429
+ guard try _fileSystemRepresentation ( withPath: srcPath, andPath: dstPath, { CopyFileW ( $0, $1, false ) } ) else {
430
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ srcPath, dstPath] )
438
431
}
439
432
}
440
433
@@ -463,8 +456,8 @@ extension FileManager {
463
456
}
464
457
465
458
while let item = enumerator. nextObject ( ) as? String {
466
- let src = joinPath ( prefix: srcPath, suffix: item)
467
- let dst = joinPath ( prefix: dstPath, suffix: item)
459
+ let src = try joinPath ( prefix: srcPath, suffix: item)
460
+ let dst = try joinPath ( prefix: dstPath, suffix: item)
468
461
469
462
let faAttributes = try windowsFileAttributes ( atPath: src)
470
463
fileType = FileAttributeType ( attributes: faAttributes, atPath: srcPath)
@@ -488,12 +481,10 @@ extension FileManager {
488
481
throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileWriteFileExists. rawValue, userInfo: [ NSFilePathErrorKey : NSString ( dstPath) ] )
489
482
}
490
483
491
- try srcPath. withCString ( encodedAs: UTF16 . self) { src in
492
- try dstPath. withCString ( encodedAs: UTF16 . self) { dst in
493
- if !MoveFileExW( src, dst, DWORD ( MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH) ) {
494
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ srcPath, dstPath] )
495
- }
496
- }
484
+ guard try _fileSystemRepresentation ( withPath: srcPath, andPath: dstPath, {
485
+ MoveFileExW ( $0, $1, DWORD ( MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH) )
486
+ } ) else {
487
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ srcPath, dstPath] )
497
488
}
498
489
}
499
490
@@ -506,12 +497,8 @@ extension FileManager {
506
497
do {
507
498
switch fileType {
508
499
case . typeRegular:
509
- try srcPath. withCString ( encodedAs: UTF16 . self) { src in
510
- try dstPath. withCString ( encodedAs: UTF16 . self) { dst in
511
- if !CreateHardLinkW( dst, src, nil ) {
512
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ srcPath, dstPath] )
513
- }
514
- }
500
+ guard try _fileSystemRepresentation ( withPath: srcPath, andPath: dstPath, { CreateHardLinkW ( $1, $0, nil ) } ) else {
501
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ srcPath, dstPath] )
515
502
}
516
503
case . typeSymbolicLink:
517
504
try _copySymlink ( atPath: srcPath, toPath: dstPath)
@@ -531,50 +518,37 @@ extension FileManager {
531
518
return
532
519
}
533
520
534
- guard path != " " else {
535
- throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileReadInvalidFileName. rawValue, userInfo: [ NSFilePathErrorKey : NSString ( path) ] )
536
- }
537
-
538
- let url = URL ( fileURLWithPath: path)
539
- var fsrBuf : [ WCHAR ] = Array < WCHAR > ( repeating: 0 , count: Int ( MAX_PATH) )
540
- _CFURLGetWideFileSystemRepresentation ( url. _cfObject, false , & fsrBuf, Int ( MAX_PATH) )
541
- let length = wcsnlen_s ( & fsrBuf, fsrBuf. count)
542
- let fsrPath = String ( utf16CodeUnits: & fsrBuf, count: length)
543
-
544
- let faAttributes = try windowsFileAttributes ( atPath: fsrPath)
545
-
521
+ let faAttributes = try windowsFileAttributes ( atPath: path)
546
522
if faAttributes. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY {
547
523
let readableAttributes = faAttributes. dwFileAttributes & DWORD ( bitPattern: ~ FILE_ATTRIBUTE_READONLY)
548
- guard fsrPath . withCString ( encodedAs : UTF16 . self , { SetFileAttributesW ( $0, readableAttributes) } ) else {
524
+ guard try _fileSystemRepresentation ( withPath : path , { SetFileAttributesW ( $0, readableAttributes) } ) else {
549
525
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ path] )
550
526
}
551
527
}
552
528
553
529
if faAttributes. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_DIRECTORY) == 0 {
554
- if !fsrPath . withCString ( encodedAs : UTF16 . self , DeleteFileW) {
530
+ guard try _fileSystemRepresentation ( withPath : path , DeleteFileW) else {
555
531
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ path] )
556
532
}
557
533
return
558
534
}
559
- var dirStack = [ fsrPath ]
535
+ var dirStack = [ path ]
560
536
var itemPath = " "
561
537
while let currentDir = dirStack. popLast ( ) {
562
538
do {
563
539
itemPath = currentDir
564
540
guard alreadyConfirmed || shouldRemoveItemAtPath ( itemPath, isURL: isURL) else {
565
541
continue
566
542
}
567
- guard !itemPath . withCString ( encodedAs : UTF16 . self , RemoveDirectoryW) else {
543
+ guard !( try _fileSystemRepresentation ( withPath : itemPath , RemoveDirectoryW) ) else {
568
544
continue
569
545
}
570
546
guard GetLastError ( ) == ERROR_DIR_NOT_EMPTY else {
571
547
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ itemPath] )
572
548
}
573
549
dirStack. append ( itemPath)
574
550
var ffd : WIN32_FIND_DATAW = WIN32_FIND_DATAW ( )
575
- let h : HANDLE = ( itemPath + " \\ * " ) . withCString ( encodedAs: UTF16 . self, {
576
- FindFirstFileW ( $0, & ffd)
577
- } )
551
+ let h : HANDLE = try _fileSystemRepresentation ( withPath: itemPath + " \\ * " , { FindFirstFileW ( $0, & ffd) } )
578
552
guard h != INVALID_HANDLE_VALUE else {
579
553
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ itemPath] )
580
554
}
@@ -589,7 +563,7 @@ extension FileManager {
589
563
590
564
if ffd. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY {
591
565
let readableAttributes = ffd. dwFileAttributes & DWORD ( bitPattern: ~ FILE_ATTRIBUTE_READONLY)
592
- guard itemPath . withCString ( encodedAs : UTF16 . self , { SetFileAttributesW ( $0, readableAttributes) } ) else {
566
+ guard try _fileSystemRepresentation ( withPath : itemPath , { SetFileAttributesW ( $0, readableAttributes) } ) else {
593
567
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ file] )
594
568
}
595
569
}
@@ -602,7 +576,7 @@ extension FileManager {
602
576
guard alreadyConfirmed || shouldRemoveItemAtPath ( itemPath, isURL: isURL) else {
603
577
continue
604
578
}
605
- if !itemPath . withCString ( encodedAs : UTF16 . self , DeleteFileW) {
579
+ guard try _fileSystemRepresentation ( withPath : itemPath , DeleteFileW) else {
606
580
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ file] )
607
581
}
608
582
}
@@ -625,7 +599,7 @@ extension FileManager {
625
599
626
600
@discardableResult
627
601
internal func _changeCurrentDirectoryPath( _ path: String ) -> Bool {
628
- return path . withCString ( encodedAs : UTF16 . self ) { SetCurrentDirectoryW ( $0 ) }
602
+ return ( try ? _fileSystemRepresentation ( withPath : path , SetCurrentDirectoryW) ) ?? false
629
603
}
630
604
631
605
internal func _fileExists( atPath path: String , isDirectory: UnsafeMutablePointer < ObjCBool > ? ) -> Bool {
@@ -636,7 +610,7 @@ extension FileManager {
636
610
let contents = try destinationOfSymbolicLink ( atPath: path)
637
611
let resolvedPath = contents. isAbsolutePath
638
612
? contents
639
- : joinPath ( prefix: path. deletingLastPathComponent, suffix: contents)
613
+ : try joinPath ( prefix: path. deletingLastPathComponent, suffix: contents)
640
614
try faAttributes = windowsFileAttributes ( atPath: resolvedPath)
641
615
} catch {
642
616
return false
@@ -745,7 +719,7 @@ extension FileManager {
745
719
}
746
720
747
721
internal func _contentsEqual( atPath path1: String , andPath path2: String ) -> Bool {
748
- guard let path1Handle = path1 . withCString ( encodedAs : UTF16 . self , {
722
+ guard let path1Handle = try ? _fileSystemRepresentation ( withPath : path1 , {
749
723
CreateFileW ( $0, GENERIC_READ, DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) , nil ,
750
724
DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS) , nil )
751
725
} ) , path1Handle != INVALID_HANDLE_VALUE else {
@@ -754,7 +728,7 @@ extension FileManager {
754
728
755
729
defer { CloseHandle ( path1Handle) }
756
730
757
- guard let path2Handle = path2 . withCString ( encodedAs : UTF16 . self , {
731
+ guard let path2Handle = try ? _fileSystemRepresentation ( withPath : path2 , {
758
732
CreateFileW ( $0, GENERIC_READ, DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) , nil ,
759
733
DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS) , nil )
760
734
} ) , path2Handle != INVALID_HANDLE_VALUE else {
@@ -828,12 +802,7 @@ extension FileManager {
828
802
}
829
803
830
804
internal func _appendSymlinkDestination( _ dest: String , toPath: String ) -> String {
831
- var isAbsolutePath : Bool = false
832
- dest. withCString ( encodedAs: UTF16 . self) {
833
- isAbsolutePath = !PathIsRelativeW( $0)
834
- }
835
-
836
- if isAbsolutePath {
805
+ if ( try ? !_fileSystemRepresentation( withPath: dest, PathIsRelativeW) ) ?? false {
837
806
return dest
838
807
}
839
808
let temp = toPath. _bridgeToObjectiveC ( ) . deletingLastPathComponent
@@ -909,11 +878,11 @@ extension FileManager {
909
878
&& attrs. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_REPARSE_POINT) == 0
910
879
if isDir && ( level == 0 || !_options. contains ( . skipsSubdirectoryDescendants) ) {
911
880
var ffd = WIN32_FIND_DATAW ( )
912
- let dirPath = joinPath ( prefix: _lastReturned. path, suffix: " * " )
913
- let handle = dirPath. withCString ( encodedAs: UTF16 . self) {
914
- FindFirstFileW ( $0, & ffd)
881
+ guard let dirPath = try ? joinPath ( prefix: _lastReturned. path, suffix: " * " ) ,
882
+ let handle = try ? FileManager . default. _fileSystemRepresentation ( withPath: dirPath, { FindFirstFileW ( $0, & ffd) } ) ,
883
+ handle != INVALID_HANDLE_VALUE else {
884
+ return firstValidItem ( )
915
885
}
916
- guard handle != INVALID_HANDLE_VALUE else { return firstValidItem ( ) }
917
886
defer { FindClose ( handle) }
918
887
919
888
repeat {
0 commit comments