Skip to content

Commit b7b5e6a

Browse files
committed
FoundationEssentials: add type to the file attributes on Windows
Get the file type using the Win32 APIs and wire that into the attribute dictionary.
1 parent f657181 commit b7b5e6a

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

Sources/FoundationEssentials/FileManager/FileManager+Files.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,20 +531,35 @@ extension _FileManagerImpl {
531531
throw CocoaError.errorWithFilePath(path, win32: GetLastError(), reading: true)
532532
}
533533

534+
let hFile = CreateFileW(pwszPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nil, OPEN_EXISTING, 0, nil)
535+
if hFile == INVALID_HANDLE_VALUE {
536+
throw CocoaError.errorWithFilePath(path, win32: GetLastError(), reading: true)
537+
}
538+
defer { CloseHandle(hFile) }
539+
540+
let dwFileType = GetFileType(hFile)
541+
let fatType: FileAttributeType = switch (dwFileType) {
542+
case FILE_TYPE_CHAR: FileAttributeType.typeCharacterSpecial
543+
case FILE_TYPE_DISK: FileAttributeType.typeRegular
544+
case FILE_TYPE_PIPE: FileAttributeType.typeSocket
545+
case FILE_TYPE_UNKNOWN: FileAttributeType.typeUnknown
546+
default: FileAttributeType.typeUnknown
547+
}
548+
534549
let size: UInt64 = (UInt64(faAttributes.nFileSizeHigh) << 32) | UInt64(faAttributes.nFileSizeLow)
535550
let creation: Date = Date(timeIntervalSince1970: faAttributes.ftCreationTime.timeIntervalSince1970)
536551
let modification: Date = Date(timeIntervalSince1970: faAttributes.ftLastWriteTime.timeIntervalSince1970)
537552
return [
538553
.size: _writeFileAttributePrimitive(size, as: UInt.self),
539554
.modificationDate: modification,
540555
.creationDate: creation,
556+
.type: fatType,
541557

542558
// TODO(compnerd) support these attributes, remapping the Windows semantics...
543559
// .posixPermissions: ...,
544560
// .referenceCount: ...,
545561
// .systemNumber: ...,
546562
// .systemFileNumber: ...,
547-
// .type: ...,
548563
// .ownerAccountID: ...,
549564
// .groupownerAccountID: ...,
550565
// .ownerAccountName: ...,

Tests/FoundationEssentialsTests/FileManager/FileManagerTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ final class FileManagerTests : XCTestCase {
635635
File("foo", attributes: [.posixPermissions : UInt16(0o644)])
636636
}.test {
637637
let attributes = try $0.attributesOfItem(atPath: "foo")
638+
#if !os(Windows)
638639
// Ensure the unconventional UInt16 was accepted as input
639640
XCTAssertEqual(attributes[.posixPermissions] as? UInt, 0o644)
640641
#if FOUNDATION_FRAMEWORK
@@ -643,6 +644,7 @@ final class FileManagerTests : XCTestCase {
643644
// Ensure that the file type can be converted to a String when it is an ObjC enum
644645
XCTAssertEqual(attributes[.type] as? String, FileAttributeType.typeRegular.rawValue)
645646
#endif
647+
#endif
646648
// Ensure that the file type can be converted to a FileAttributeType when it is an ObjC enum and in swift-foundation
647649
XCTAssertEqual(attributes[.type] as? FileAttributeType, .typeRegular)
648650

0 commit comments

Comments
 (0)