@@ -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,70 @@ 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
+ let err = GetLastError ( )
1832
+ if err == ERROR_FILE_NOT_FOUND {
1833
+ errno = ENOENT
1834
+ }
1835
+ throw _NSErrorWithErrno ( errno, reading: true , path: path)
1836
+ }
1837
+ var info : BY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION ( )
1838
+ GetFileInformationByHandle ( h, & info)
1839
+ // Group id is always 0 on Windows
1840
+ statInfo. st_gid = 0
1841
+ statInfo. st_atime = info. ftLastAccessTime. time_t
1842
+ statInfo. st_ctime = info. ftCreationTime. time_t
1843
+ statInfo. st_dev = info. dwVolumeSerialNumber
1844
+ // inodes have meaning on FAT/HPFS/NTFS
1845
+ statInfo. st_ino = 0
1846
+ statInfo. st_rdev = info. dwVolumeSerialNumber
1847
+ statInfo. st_mode =
1848
+ // On a symlink to a directory, Windows sets both the REPARSE_POINT and
1849
+ // DIRECTORY attributes. Since Windows doesn't provide S_IFLNK and we
1850
+ // want unix style "symlinks to directories are not directories
1851
+ // themselves, we say symlinks are regular files
1852
+ UInt16 ( ( info. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_REPARSE_POINT) ) != 0
1853
+ ? _S_IFREG
1854
+ : ( info. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_DIRECTORY) ) != 0
1855
+ ? _S_IFDIR
1856
+ : _S_IFREG)
1857
+ statInfo. st_mode |= UInt16 ( ( info. dwFileAttributes & DWORD ( FILE_ATTRIBUTE_READONLY) ) != 0
1858
+ ? _S_IREAD
1859
+ : _S_IREAD | _S_IWRITE)
1860
+
1861
+ statInfo. st_mode |= UInt16 ( _S_IEXEC)
1862
+ statInfo. st_mtime = info. ftLastWriteTime. time_t
1863
+ statInfo. st_nlink = Int16 ( info. nNumberOfLinks)
1864
+ if info. nFileSizeHigh != 0 {
1865
+ throw _NSErrorWithErrno ( EOVERFLOW, reading: true , path: path)
1866
+ }
1867
+ statInfo. st_size = Int32 ( info. nFileSizeLow)
1868
+ // Uid is always 0 on Windows systems
1869
+ statInfo. st_uid = 0
1870
+ CloseHandle ( h)
1871
+ #else
1821
1872
guard lstat ( _fsRep, & statInfo) == 0 else {
1822
1873
throw _NSErrorWithErrno ( errno, reading: true , path: path)
1823
1874
}
1875
+ #endif
1824
1876
return statInfo
1825
1877
}
1826
- #endif
1827
1878
1828
- @available ( Windows, deprecated, message: " Not Yet Implemented " )
1829
1879
internal func _permissionsOfItem( atPath path: String ) throws -> Int {
1880
+ let fileInfo = try _lstatFile ( atPath: path)
1830
1881
#if os(Windows)
1831
- NSUnimplemented ( )
1882
+ return Int ( fileInfo . st_mode & ~ UInt16 ( ucrt . S_IFMT ) )
1832
1883
#else
1833
- let fileInfo = try _lstatFile ( atPath: path)
1834
1884
return Int ( fileInfo. st_mode & ~ S_IFMT)
1835
1885
#endif
1836
1886
}
0 commit comments