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)
@@ -220,17 +218,17 @@ extension FileManager {
220
218
try _contentsOfDir ( atPath: path, { ( entryName, entryType) throws in
221
219
contents. append ( entryName)
222
220
if entryType & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY {
223
- let subPath : String = joinPath ( prefix: path, suffix: entryName)
221
+ let subPath : String = try joinPath ( prefix: path, suffix: entryName)
224
222
let entries = try subpathsOfDirectory ( atPath: subPath)
225
- contents. append ( contentsOf: entries. map { joinPath ( prefix: entryName, suffix: $0) . standardizingPath } )
223
+ contents. append ( contentsOf: try entries. map { try joinPath ( prefix: entryName, suffix: $0) . standardizingPath } )
226
224
}
227
225
} )
228
226
return contents
229
227
}
230
228
231
229
internal func windowsFileAttributes( atPath path: String ) throws -> WIN32_FILE_ATTRIBUTE_DATA {
232
230
var faAttributes : WIN32_FILE_ATTRIBUTE_DATA = WIN32_FILE_ATTRIBUTE_DATA ( )
233
- return try path . withCString ( encodedAs : UTF16 . self ) {
231
+ return try _fileSystemRepresentation ( withPath : path ) {
234
232
if !GetFileAttributesExW( $0, GetFileExInfoStandard, & faAttributes) {
235
233
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path] )
236
234
}
@@ -245,7 +243,7 @@ extension FileManager {
245
243
internal func _attributesOfFileSystem( forPath path: String ) throws -> [ FileAttributeKey : Any ] {
246
244
var result : [ FileAttributeKey : Any ] = [ : ]
247
245
248
- try path . withCString ( encodedAs : UTF16 . self ) {
246
+ try _fileSystemRepresentation ( withPath : path ) {
249
247
let dwLength : DWORD = GetFullPathNameW ( $0, 0 , nil , nil )
250
248
guard dwLength != 0 else {
251
249
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path] )
@@ -291,18 +289,14 @@ extension FileManager {
291
289
dwFlags |= DWORD ( SYMBOLIC_LINK_FLAG_DIRECTORY)
292
290
}
293
291
294
- try path. withCString ( encodedAs: UTF16 . self) { name in
295
- try destPath. withCString ( encodedAs: UTF16 . self) { dest in
296
- guard CreateSymbolicLinkW ( name, dest, dwFlags) != 0 else {
297
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path, destPath] )
298
- }
299
- }
292
+ guard try _fileSystemRepresentation ( withPath: path, andPath: destPath, { CreateSymbolicLinkW ( $0, $1, dwFlags) != 0 } ) else {
293
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ path, destPath] )
300
294
}
301
295
}
302
296
303
297
internal func _destinationOfSymbolicLink( atPath path: String ) throws -> String {
304
- let handle = path . withCString ( encodedAs : UTF16 . self ) { symlink in
305
- CreateFileW ( symlink ,
298
+ let handle = try _fileSystemRepresentation ( withPath : path ) {
299
+ CreateFileW ( $0 ,
306
300
GENERIC_READ,
307
301
DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
308
302
nil ,
@@ -355,16 +349,15 @@ extension FileManager {
355
349
}
356
350
357
351
internal func _canonicalizedPath( toFileAtPath path: String ) throws -> String {
358
- var hFile : HANDLE = INVALID_HANDLE_VALUE
359
- path. withCString ( encodedAs: UTF16 . self) { link in
360
- // BACKUP_SEMANTICS are (confusingly) required in order to receive a
361
- // handle to a directory
362
- hFile = CreateFileW ( link, 0 , DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
363
- nil , DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_BACKUP_SEMANTICS) ,
364
- nil )
352
+ var hFile : HANDLE = try _fileSystemRepresentation ( withPath: path) {
353
+ // BACKUP_SEMANTICS are (confusingly) required in order to receive a
354
+ // handle to a directory
355
+ CreateFileW ( $0, 0 , DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
356
+ nil , DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_BACKUP_SEMANTICS) ,
357
+ nil )
365
358
}
366
359
guard hFile != INVALID_HANDLE_VALUE else {
367
- return try path . withCString ( encodedAs : UTF16 . self ) {
360
+ return try _fileSystemRepresentation ( withPath : path ) {
368
361
var dwLength = GetFullPathNameW ( $0, 0 , nil , nil )
369
362
var szPath = Array < WCHAR > ( repeating: 0 , count: Int ( dwLength + 1 ) )
370
363
dwLength = GetFullPathNameW ( $0, DWORD ( szPath. count) , & szPath, nil )
@@ -384,12 +377,8 @@ extension FileManager {
384
377
}
385
378
386
379
internal func _copyRegularFile( atPath srcPath: String , toPath dstPath: String , variant: String = " Copy " ) throws {
387
- try srcPath. withCString ( encodedAs: UTF16 . self) { src in
388
- try dstPath. withCString ( encodedAs: UTF16 . self) { dst in
389
- if !CopyFileW( src, dst, false ) {
390
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ srcPath, dstPath] )
391
- }
392
- }
380
+ guard try _fileSystemRepresentation ( withPath: srcPath, andPath: dstPath, { CopyFileW ( $0, $1, false ) } ) else {
381
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ srcPath, dstPath] )
393
382
}
394
383
}
395
384
@@ -420,8 +409,8 @@ extension FileManager {
420
409
}
421
410
422
411
while let item = enumerator. nextObject ( ) as? String {
423
- let src = joinPath ( prefix: srcPath, suffix: item)
424
- let dst = joinPath ( prefix: dstPath, suffix: item)
412
+ let src = try joinPath ( prefix: srcPath, suffix: item)
413
+ let dst = try joinPath ( prefix: dstPath, suffix: item)
425
414
426
415
let faAttributes = try windowsFileAttributes ( atPath: src)
427
416
fileType = FileAttributeType ( attributes: faAttributes, atPath: srcPath)
@@ -445,12 +434,10 @@ extension FileManager {
445
434
throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileWriteFileExists. rawValue, userInfo: [ NSFilePathErrorKey : NSString ( dstPath) ] )
446
435
}
447
436
448
- try srcPath. withCString ( encodedAs: UTF16 . self) { src in
449
- try dstPath. withCString ( encodedAs: UTF16 . self) { dst in
450
- if !MoveFileExW( src, dst, DWORD ( MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH) ) {
451
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ srcPath, dstPath] )
452
- }
453
- }
437
+ guard try _fileSystemRepresentation ( withPath: srcPath, andPath: dstPath, {
438
+ MoveFileExW ( $0, $1, DWORD ( MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH) )
439
+ } ) else {
440
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ srcPath, dstPath] )
454
441
}
455
442
}
456
443
@@ -463,12 +450,8 @@ extension FileManager {
463
450
do {
464
451
switch fileType {
465
452
case . typeRegular:
466
- try srcPath. withCString ( encodedAs: UTF16 . self) { src in
467
- try dstPath. withCString ( encodedAs: UTF16 . self) { dst in
468
- if !CreateHardLinkW( dst, src, nil ) {
469
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ srcPath, dstPath] )
470
- }
471
- }
453
+ guard try _fileSystemRepresentation ( withPath: srcPath, andPath: dstPath, { CreateHardLinkW ( $1, $0, nil ) } ) else {
454
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ srcPath, dstPath] )
472
455
}
473
456
case . typeSymbolicLink:
474
457
try _copySymlink ( atPath: srcPath, toPath: dstPath)
@@ -488,50 +471,37 @@ extension FileManager {
488
471
return
489
472
}
490
473
491
- guard path != " " else {
492
- throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . fileReadInvalidFileName. rawValue, userInfo: [ NSFilePathErrorKey : NSString ( path) ] )
493
- }
494
-
495
- let url = URL ( fileURLWithPath: path)
496
- var fsrBuf : [ WCHAR ] = Array < WCHAR > ( repeating: 0 , count: Int ( MAX_PATH) )
497
- _CFURLGetWideFileSystemRepresentation ( url. _cfObject, false , & fsrBuf, Int ( MAX_PATH) )
498
- let length = wcsnlen_s ( & fsrBuf, fsrBuf. count)
499
- let fsrPath = String ( utf16CodeUnits: & fsrBuf, count: length)
500
-
501
- let faAttributes = try windowsFileAttributes ( atPath: fsrPath)
502
-
474
+ let faAttributes = try windowsFileAttributes ( atPath: path)
503
475
if faAttributes. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY {
504
476
let readableAttributes = faAttributes. dwFileAttributes & DWORD ( bitPattern: ~ FILE_ATTRIBUTE_READONLY)
505
- guard fsrPath . withCString ( encodedAs : UTF16 . self , { SetFileAttributesW ( $0, readableAttributes) } ) else {
477
+ guard try _fileSystemRepresentation ( withPath : path , { SetFileAttributesW ( $0, readableAttributes) } ) else {
506
478
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ path] )
507
479
}
508
480
}
509
481
510
482
if faAttributes. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_DIRECTORY) == 0 {
511
- if !fsrPath . withCString ( encodedAs : UTF16 . self , DeleteFileW) {
483
+ guard try _fileSystemRepresentation ( withPath : path , DeleteFileW) else {
512
484
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ path] )
513
485
}
514
486
return
515
487
}
516
- var dirStack = [ fsrPath ]
488
+ var dirStack = [ path ]
517
489
var itemPath = " "
518
490
while let currentDir = dirStack. popLast ( ) {
519
491
do {
520
492
itemPath = currentDir
521
493
guard alreadyConfirmed || shouldRemoveItemAtPath ( itemPath, isURL: isURL) else {
522
494
continue
523
495
}
524
- guard !itemPath . withCString ( encodedAs : UTF16 . self , RemoveDirectoryW) else {
496
+ guard !( try _fileSystemRepresentation ( withPath : itemPath , RemoveDirectoryW) ) else {
525
497
continue
526
498
}
527
499
guard GetLastError ( ) == ERROR_DIR_NOT_EMPTY else {
528
500
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ itemPath] )
529
501
}
530
502
dirStack. append ( itemPath)
531
503
var ffd : WIN32_FIND_DATAW = WIN32_FIND_DATAW ( )
532
- let h : HANDLE = ( itemPath + " \\ * " ) . withCString ( encodedAs: UTF16 . self, {
533
- FindFirstFileW ( $0, & ffd)
534
- } )
504
+ let h : HANDLE = try _fileSystemRepresentation ( withPath: itemPath + " \\ * " , { FindFirstFileW ( $0, & ffd) } )
535
505
guard h != INVALID_HANDLE_VALUE else {
536
506
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ itemPath] )
537
507
}
@@ -546,7 +516,7 @@ extension FileManager {
546
516
547
517
if ffd. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY {
548
518
let readableAttributes = ffd. dwFileAttributes & DWORD ( bitPattern: ~ FILE_ATTRIBUTE_READONLY)
549
- guard file . withCString ( encodedAs : UTF16 . self , { SetFileAttributesW ( $0, readableAttributes) } ) else {
519
+ guard try _fileSystemRepresentation ( withPath : file , { SetFileAttributesW ( $0, readableAttributes) } ) else {
550
520
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ file] )
551
521
}
552
522
}
@@ -559,7 +529,7 @@ extension FileManager {
559
529
guard alreadyConfirmed || shouldRemoveItemAtPath ( itemPath, isURL: isURL) else {
560
530
continue
561
531
}
562
- if !itemPath . withCString ( encodedAs : UTF16 . self , DeleteFileW) {
532
+ guard try _fileSystemRepresentation ( withPath : itemPath , DeleteFileW) else {
563
533
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ file] )
564
534
}
565
535
}
@@ -582,7 +552,7 @@ extension FileManager {
582
552
583
553
@discardableResult
584
554
internal func _changeCurrentDirectoryPath( _ path: String ) -> Bool {
585
- return path . withCString ( encodedAs : UTF16 . self ) { SetCurrentDirectoryW ( $0 ) }
555
+ return ( try ? _fileSystemRepresentation ( withPath : path , SetCurrentDirectoryW) ) ?? false
586
556
}
587
557
588
558
internal func _fileExists( atPath path: String , isDirectory: UnsafeMutablePointer < ObjCBool > ? ) -> Bool {
@@ -775,11 +745,11 @@ extension FileManager {
775
745
776
746
if isDir. boolValue && ( level == 0 || !_options. contains ( . skipsSubdirectoryDescendants) ) {
777
747
var ffd = WIN32_FIND_DATAW ( )
778
- let dirPath = joinPath ( prefix: _lastReturned. path, suffix: " * " )
779
- let handle = dirPath. withCString ( encodedAs: UTF16 . self) {
780
- FindFirstFileW ( $0, & ffd)
748
+ guard let dirPath = try ? joinPath ( prefix: _lastReturned. path, suffix: " * " ) ,
749
+ let handle = try ? FileManager . default. _fileSystemRepresentation ( withPath: dirPath, { FindFirstFileW ( $0, & ffd) } ) ,
750
+ handle != INVALID_HANDLE_VALUE else {
751
+ return firstValidItem ( )
781
752
}
782
- guard handle != INVALID_HANDLE_VALUE else { return firstValidItem ( ) }
783
753
defer { FindClose ( handle) }
784
754
785
755
repeat {
0 commit comments