@@ -553,48 +553,64 @@ extension _FileManagerImpl {
553
553
func attributesOfItem( atPath path: String ) throws -> [ FileAttributeKey : Any ] {
554
554
#if os(Windows)
555
555
return try path. withNTPathRepresentation { pwszPath in
556
- var faAttributes : WIN32_FILE_ATTRIBUTE_DATA = . init( )
557
- guard GetFileAttributesExW ( pwszPath, GetFileExInfoStandard, & faAttributes) else {
558
- throw CocoaError . errorWithFilePath ( path, win32: GetLastError ( ) , reading: true )
559
- }
560
-
561
556
let hFile = CreateFileW ( pwszPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nil , OPEN_EXISTING, 0 , nil )
562
557
if hFile == INVALID_HANDLE_VALUE {
563
558
throw CocoaError . errorWithFilePath ( path, win32: GetLastError ( ) , reading: true )
564
559
}
565
560
defer { CloseHandle ( hFile) }
566
561
562
+ var info : BY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION ( )
563
+ guard GetFileInformationByHandle ( hFile, & info) else {
564
+ throw CocoaError . errorWithFilePath ( path, win32: GetLastError ( ) , reading: true )
565
+ }
566
+
567
567
let dwFileType = GetFileType ( hFile)
568
568
let fatType : FileAttributeType = switch ( dwFileType) {
569
569
case FILE_TYPE_CHAR: FileAttributeType . typeCharacterSpecial
570
570
case FILE_TYPE_DISK:
571
- faAttributes . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY
571
+ info . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY
572
572
? FileAttributeType . typeDirectory
573
573
: FileAttributeType . typeRegular
574
574
case FILE_TYPE_PIPE: FileAttributeType . typeSocket
575
575
case FILE_TYPE_UNKNOWN: FileAttributeType . typeUnknown
576
576
default : FileAttributeType . typeUnknown
577
577
}
578
578
579
- let size : UInt64 = ( UInt64 ( faAttributes. nFileSizeHigh) << 32 ) | UInt64 ( faAttributes. nFileSizeLow)
580
- let creation : Date = Date ( timeIntervalSince1970: faAttributes. ftCreationTime. timeIntervalSince1970)
581
- let modification : Date = Date ( timeIntervalSince1970: faAttributes. ftLastWriteTime. timeIntervalSince1970)
579
+ let systemNumber = UInt64 ( info. dwVolumeSerialNumber)
580
+ let systemFileNumber = UInt64 ( info. nFileIndexHigh << 32 ) | UInt64 ( info. nFileIndexLow)
581
+ let referenceCount = UInt64 ( info. nNumberOfLinks)
582
+
583
+ let isReadOnly = info. dwFileAttributes & FILE_ATTRIBUTE_READONLY != 0
584
+ // Directories are always considered executable, but we check for other types
585
+ let isExecutable = fatType == . typeDirectory || SaferiIsExecutableFileType ( pwszPath, 0 )
586
+ var posixPermissions = UInt16 ( _S_IREAD)
587
+ if !isReadOnly {
588
+ posixPermissions |= UInt16 ( _S_IWRITE)
589
+ }
590
+ if isExecutable {
591
+ posixPermissions |= UInt16 ( _S_IEXEC)
592
+ }
593
+
594
+ let size : UInt64 = ( UInt64 ( info. nFileSizeHigh) << 32 ) | UInt64 ( info. nFileSizeLow)
595
+ let creation : Date = Date ( timeIntervalSince1970: info. ftCreationTime. timeIntervalSince1970)
596
+ let modification : Date = Date ( timeIntervalSince1970: info. ftLastWriteTime. timeIntervalSince1970)
582
597
return [
583
598
. size: _writeFileAttributePrimitive ( size, as: UInt . self) ,
584
599
. modificationDate: modification,
585
600
. creationDate: creation,
586
601
. type: fatType,
602
+ . systemNumber: _writeFileAttributePrimitive ( systemNumber, as: UInt . self) ,
603
+ . systemFileNumber: _writeFileAttributePrimitive ( systemFileNumber, as: UInt . self) ,
604
+ . posixPermissions: _writeFileAttributePrimitive ( posixPermissions, as: UInt . self) ,
605
+ . referenceCount: _writeFileAttributePrimitive ( referenceCount, as: UInt . self) ,
606
+
607
+ // Uid is always 0 on Windows systems
608
+ . ownerAccountID: _writeFileAttributePrimitive ( 0 , as: UInt . self) ,
609
+
610
+ // Group id is always 0 on Windows
611
+ . groupOwnerAccountID: _writeFileAttributePrimitive ( 0 , as: UInt . self)
587
612
588
- // TODO(compnerd) support these attributes, remapping the Windows semantics...
589
- // .posixPermissions: ...,
590
- // .referenceCount: ...,
591
- // .systemNumber: ...,
592
- // .systemFileNumber: ...,
593
- // .ownerAccountID: ...,
594
- // .groupownerAccountID: ...,
595
- // .ownerAccountName: ...,
596
- // .groupOwnerAccountName: ...,
597
- // .deviceIdentifier: ...,
613
+ // TODO: Support .deviceIdentifier
598
614
]
599
615
}
600
616
#else
0 commit comments