@@ -1804,7 +1804,6 @@ open class FileManager : NSObject {
1804
1804
return path1entries. isEmpty
1805
1805
}
1806
1806
1807
- #if !os(Windows)
1808
1807
private func _lstatFile( atPath path: String , withFileSystemRepresentation fsRep: UnsafePointer < Int8 > ? = nil ) throws -> stat {
1809
1808
let _fsRep : UnsafePointer < Int8 >
1810
1809
if fsRep == nil {
@@ -1818,19 +1817,64 @@ open class FileManager : NSObject {
1818
1817
}
1819
1818
1820
1819
var statInfo = stat ( )
1820
+ #if os(Windows)
1821
+ let h = path. withCString ( encodedAs: UTF16 . self) {
1822
+ CreateFileW ( /*lpFileName=*/$0,
1823
+ /*dwDesiredAccess=*/DWORD ( 0 ) ,
1824
+ /*dwShareMode=*/DWORD ( FILE_SHARE_READ) ,
1825
+ /*lpSecurityAttributes=*/nil ,
1826
+ /*dwCreationDisposition=*/DWORD ( OPEN_EXISTING) ,
1827
+ /*dwFlagsAndAttributes=*/DWORD ( FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS) ,
1828
+ /*hTemplateFile=*/nil )
1829
+ }
1830
+ if h == INVALID_HANDLE_VALUE {
1831
+ throw _NSErrorWithWindowsError ( GetLastError ( ) , reading: false )
1832
+ }
1833
+ var info : BY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION ( )
1834
+ GetFileInformationByHandle ( h, & info)
1835
+ // Group id is always 0 on Windows
1836
+ statInfo. st_gid = 0
1837
+ statInfo. st_atime = info. ftLastAccessTime. time_t
1838
+ statInfo. st_ctime = info. ftCreationTime. time_t
1839
+ statInfo. st_dev = info. dwVolumeSerialNumber
1840
+ // inodes have meaning on FAT/HPFS/NTFS
1841
+ statInfo. st_ino = 0
1842
+ statInfo. st_rdev = info. dwVolumeSerialNumber
1843
+
1844
+ let isReparsePoint = info. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_REPARSE_POINT) != 0
1845
+ let isDir = info. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_DIRECTORY) != 0
1846
+ let fileMode = isDir ? _S_IFDIR : _S_IFREG
1847
+ // On a symlink to a directory, Windows sets both the REPARSE_POINT and
1848
+ // DIRECTORY attributes. Since Windows doesn't provide S_IFLNK and we
1849
+ // want unix style "symlinks to directories are not directories
1850
+ // themselves, we say symlinks are regular files
1851
+ statInfo. st_mode = UInt16 ( isReparsePoint ? _S_IFREG : fileMode)
1852
+ let isReadOnly = info. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_READONLY) != 0
1853
+ statInfo. st_mode |= UInt16 ( isReadOnly ? _S_IREAD : ( _S_IREAD | _S_IWRITE) )
1854
+ statInfo. st_mode |= UInt16 ( _S_IEXEC)
1855
+
1856
+ statInfo. st_mtime = info. ftLastWriteTime. time_t
1857
+ statInfo. st_nlink = Int16 ( info. nNumberOfLinks)
1858
+ if info. nFileSizeHigh != 0 {
1859
+ throw _NSErrorWithErrno ( EOVERFLOW, reading: true , path: path)
1860
+ }
1861
+ statInfo. st_size = Int32 ( info. nFileSizeLow)
1862
+ // Uid is always 0 on Windows systems
1863
+ statInfo. st_uid = 0
1864
+ CloseHandle ( h)
1865
+ #else
1821
1866
guard lstat ( _fsRep, & statInfo) == 0 else {
1822
1867
throw _NSErrorWithErrno ( errno, reading: true , path: path)
1823
1868
}
1869
+ #endif
1824
1870
return statInfo
1825
1871
}
1826
- #endif
1827
1872
1828
- @available ( Windows, deprecated, message: " Not Yet Implemented " )
1829
1873
internal func _permissionsOfItem( atPath path: String ) throws -> Int {
1874
+ let fileInfo = try _lstatFile ( atPath: path)
1830
1875
#if os(Windows)
1831
- NSUnimplemented ( )
1876
+ return Int ( fileInfo . st_mode & ~ UInt16 ( ucrt . S_IFMT ) )
1832
1877
#else
1833
- let fileInfo = try _lstatFile ( atPath: path)
1834
1878
return Int ( fileInfo. st_mode & ~ S_IFMT)
1835
1879
#endif
1836
1880
}
0 commit comments