@@ -583,21 +583,24 @@ extension FileManager {
583
583
}
584
584
dirStack. append ( itemPath)
585
585
var ffd : WIN32_FIND_DATAW = WIN32_FIND_DATAW ( )
586
- let h : HANDLE = ( itemPath + " \\ * " ) . withCString ( encodedAs: UTF16 . self, {
587
- FindFirstFileW ( $0, & ffd)
588
- } )
589
- guard h != INVALID_HANDLE_VALUE else {
590
- throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ itemPath] )
586
+ let capacity = MemoryLayout . size ( ofValue: ffd. cFileName)
587
+
588
+ let handle : HANDLE = try FileManager . default. _fileSystemRepresentation ( withPath: joinPath ( prefix: itemPath, suffix: " * " ) ) {
589
+ FindFirstFileW ( $0, & ffd)
591
590
}
592
- defer { FindClose ( h) }
591
+ if handle == INVALID_HANDLE_VALUE {
592
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ itemPath] )
593
+ }
594
+ defer { FindClose ( handle) }
593
595
594
596
repeat {
595
- let fileArr = Array < WCHAR > (
596
- UnsafeBufferPointer ( start : & ffd . cFileName . 0 ,
597
- count : MemoryLayout . size ( ofValue : ffd . cFileName ) ) )
598
- let file = String ( decodingCString : fileArr , as : UTF16 . self )
599
- itemPath = " \( currentDir ) \\ \( file ) "
597
+ let file = withUnsafePointer ( to : & ffd . cFileName ) {
598
+ $0 . withMemoryRebound ( to : WCHAR . self , capacity : capacity ) {
599
+ String ( decodingCString : $0 , as : UTF16 . self )
600
+ }
601
+ }
600
602
603
+ itemPath = " \( currentDir) \\ \( file) "
601
604
if ffd. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY {
602
605
let readableAttributes = ffd. dwFileAttributes & DWORD ( bitPattern: ~ FILE_ATTRIBUTE_READONLY)
603
606
guard itemPath. withCString ( encodedAs: UTF16 . self, { SetFileAttributesW ( $0, readableAttributes) } ) else {
@@ -617,7 +620,7 @@ extension FileManager {
617
620
throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false , paths: [ file] )
618
621
}
619
622
}
620
- } while FindNextFileW ( h , & ffd)
623
+ } while FindNextFileW ( handle , & ffd)
621
624
} catch {
622
625
if !shouldProceedAfterError( error, removingItemAtPath: itemPath, isURL: isURL) {
623
626
throw error
@@ -646,18 +649,24 @@ extension FileManager {
646
649
var faAttributes : WIN32_FILE_ATTRIBUTE_DATA = WIN32_FILE_ATTRIBUTE_DATA ( )
647
650
do { faAttributes = try windowsFileAttributes ( atPath: path) } catch { return false }
648
651
if faAttributes. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_REPARSE_POINT) == DWORD ( FILE_ATTRIBUTE_REPARSE_POINT) {
649
- do {
650
- let contents = try destinationOfSymbolicLink ( atPath: path)
651
- let resolvedPath = contents. isAbsolutePath
652
- ? contents
653
- : joinPath ( prefix: path. deletingLastPathComponent, suffix: contents)
654
- try faAttributes = windowsFileAttributes ( atPath: resolvedPath)
655
- } catch {
656
- return false
657
- }
658
- }
659
- if let isDirectory = isDirectory {
652
+ guard let handle: HANDLE = try ? FileManager . default. _fileSystemRepresentation ( withPath: path, {
653
+ CreateFileW ( $0, /* dwDesiredAccess= */ DWORD ( 0 ) ,
654
+ DWORD ( FILE_SHARE_READ) , /* lpSecurityAttributes= */ nil ,
655
+ DWORD ( OPEN_EXISTING) ,
656
+ DWORD ( FILE_FLAG_BACKUP_SEMANTICS) , /* hTemplateFile= */ nil )
657
+ } ) else { return false }
658
+ if handle == INVALID_HANDLE_VALUE { return false }
659
+ defer { CloseHandle ( handle) }
660
+
661
+ if let isDirectory = isDirectory {
662
+ var info : BY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION ( )
663
+ GetFileInformationByHandle ( handle, & info)
664
+ isDirectory. pointee = ObjCBool ( info. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_DIRECTORY) == DWORD ( FILE_ATTRIBUTE_DIRECTORY) )
665
+ }
666
+ } else {
667
+ if let isDirectory = isDirectory {
660
668
isDirectory. pointee = ObjCBool ( faAttributes. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_DIRECTORY) == DWORD ( FILE_ATTRIBUTE_DIRECTORY) )
669
+ }
661
670
}
662
671
return true
663
672
}
@@ -758,21 +767,24 @@ extension FileManager {
758
767
}
759
768
760
769
internal func _contentsEqual( atPath path1: String , andPath path2: String ) -> Bool {
761
- guard let path1Handle = path1. withCString ( encodedAs: UTF16 . self, {
762
- CreateFileW ( $0, GENERIC_READ, DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) , nil ,
763
- DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS) , nil )
764
- } ) , path1Handle != INVALID_HANDLE_VALUE else {
765
- return false
766
- }
767
-
770
+ guard let path1Handle: HANDLE = try ? FileManager . default. _fileSystemRepresentation ( withPath: path1, {
771
+ CreateFileW ( $0, GENERIC_READ,
772
+ DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
773
+ nil , DWORD ( OPEN_EXISTING) ,
774
+ DWORD ( FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS) ,
775
+ nil )
776
+ } ) else { return false }
777
+ if path1Handle == INVALID_HANDLE_VALUE { return false }
768
778
defer { CloseHandle ( path1Handle) }
769
779
770
- guard let path2Handle = path2. withCString ( encodedAs: UTF16 . self, {
771
- CreateFileW ( $0, GENERIC_READ, DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) , nil ,
772
- DWORD ( OPEN_EXISTING) , DWORD ( FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS) , nil )
773
- } ) , path2Handle != INVALID_HANDLE_VALUE else {
774
- return false
775
- }
780
+ guard let path2Handle: HANDLE = try ? FileManager . default. _fileSystemRepresentation ( withPath: path2, {
781
+ CreateFileW ( $0, GENERIC_READ,
782
+ DWORD ( FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ,
783
+ nil , DWORD ( OPEN_EXISTING) ,
784
+ DWORD ( FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS) ,
785
+ nil )
786
+ } ) else { return false }
787
+ if path2Handle == INVALID_HANDLE_VALUE { return false }
776
788
defer { CloseHandle ( path2Handle) }
777
789
778
790
let file1Type = GetFileType ( path1Handle)
@@ -829,14 +841,12 @@ extension FileManager {
829
841
return true
830
842
}
831
843
832
- let path1Fsr = fileSystemRepresentation ( withPath: path1)
833
- defer { path1Fsr. deallocate ( ) }
834
- let path2Fsr = fileSystemRepresentation ( withPath: path2)
835
- defer { path2Fsr. deallocate ( ) }
836
- return _compareFiles ( withFileSystemRepresentation: path1Fsr,
837
- andFileSystemRepresentation: path2Fsr,
838
- size: ( Int64 ( path1FileInfo. nFileSizeHigh) << 32 ) | Int64 ( path1FileInfo. nFileSizeLow) ,
839
- bufSize: 0x1000 )
844
+ return try ! FileManager . default. _fileSystemRepresentation ( withPath: path1, andPath: path2) {
845
+ _compareFiles ( withFileSystemRepresentation: $0,
846
+ andFileSystemRepresentation: $1,
847
+ size: ( Int64 ( path1FileInfo. nFileSizeHigh) << 32 ) | Int64 ( path1FileInfo. nFileSizeLow) ,
848
+ bufSize: 0x1000 )
849
+ }
840
850
}
841
851
}
842
852
@@ -891,10 +901,13 @@ extension FileManager {
891
901
func firstValidItem( ) -> URL ? {
892
902
while let url = _stack. popLast ( ) {
893
903
if !FileManager. default. fileExists ( atPath: url. path) {
894
- guard let handler = _errorHandler,
895
- handler ( url, _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ url. path] ) )
896
- else { return nil }
897
- continue
904
+ if let handler = _errorHandler {
905
+ if !handler( url, _NSErrorWithWindowsError ( GetLastError ( ) , reading: true , paths: [ url. path] ) ) {
906
+ return nil
907
+ }
908
+ } else {
909
+ return nil
910
+ }
898
911
}
899
912
_lastReturned = url
900
913
return _lastReturned
@@ -910,31 +923,32 @@ extension FileManager {
910
923
return firstValidItem ( )
911
924
}
912
925
913
- let isDir = attrs. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_DIRECTORY) == DWORD ( FILE_ATTRIBUTE_DIRECTORY)
914
- && attrs. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_REPARSE_POINT) == 0
926
+ let isDir = attrs. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_DIRECTORY) == DWORD ( FILE_ATTRIBUTE_DIRECTORY) &&
927
+ attrs. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_REPARSE_POINT) == 0
915
928
if isDir && ( level == 0 || !_options. contains ( . skipsSubdirectoryDescendants) ) {
916
929
var ffd = WIN32_FIND_DATAW ( )
917
- let dirPath = joinPath ( prefix: _lastReturned. path, suffix: " * " )
918
- let handle = try ? FileManager . default. _fileSystemRepresentation ( withPath: dirPath) {
930
+ let capacity = MemoryLayout . size ( ofValue: ffd. cFileName)
931
+
932
+ guard let handle = try ? FileManager . default. _fileSystemRepresentation ( withPath: joinPath ( prefix: _lastReturned. path, suffix: " * " ) , {
919
933
FindFirstFileW ( $0, & ffd)
920
- }
934
+ } ) else { return firstValidItem ( ) }
921
935
if handle == INVALID_HANDLE_VALUE { return firstValidItem ( ) }
922
936
defer { FindClose ( handle) }
923
937
924
938
repeat {
925
- let fileArr = Array < WCHAR > (
926
- UnsafeBufferPointer ( start: & ffd. cFileName. 0 ,
927
- count: MemoryLayout . size ( ofValue: ffd. cFileName) ) )
928
- let file = String ( decodingCString: fileArr, as: UTF16 . self)
929
- if file != " . " && file != " .. "
930
- && ( !_options. contains ( . skipsHiddenFiles)
931
- || ( ffd. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_HIDDEN) == 0 ) ) {
932
- let relative = URL ( fileURLWithPath: file, relativeTo: _lastReturned)
933
- _stack. append ( relative)
939
+ let file = withUnsafePointer ( to: & ffd. cFileName) {
940
+ $0. withMemoryRebound ( to: WCHAR . self, capacity: capacity) {
941
+ String ( decodingCString: $0, as: UTF16 . self)
942
+ }
934
943
}
944
+ if file == " . " || file == " .. " { continue }
945
+ if _options. contains ( . skipsHiddenFiles) &&
946
+ ffd. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_HIDDEN) == DWORD ( FILE_ATTRIBUTE_HIDDEN) {
947
+ continue
948
+ }
949
+ _stack. append ( URL ( fileURLWithPath: file, relativeTo: _lastReturned) )
935
950
} while FindNextFileW ( handle, & ffd)
936
951
}
937
-
938
952
return firstValidItem ( )
939
953
}
940
954
0 commit comments