Skip to content

Commit 0ea3e4d

Browse files
committed
Windows: Implement attributesOfItem with _lstat
1 parent a733b6b commit 0ea3e4d

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

Foundation/FileManager.swift

+23-19
Original file line numberDiff line numberDiff line change
@@ -871,14 +871,6 @@ open class FileManager : NSObject {
871871
open func attributesOfItem(atPath path: String) throws -> [FileAttributeKey : Any] {
872872
var result: [FileAttributeKey:Any] = [:]
873873

874-
#if os(Windows)
875-
let faAttributes: WIN32_FILE_ATTRIBUTE_DATA = try windowsFileAttributes(atPath: path)
876-
877-
result[.size] = NSNumber(value: (faAttributes.nFileSizeHigh << 32) | faAttributes.nFileSizeLow)
878-
result[.modificationDate] = Date(timeIntervalSinceReferenceDate: TimeInterval(faAttributes.ftLastWriteTime))
879-
// FIXME(compnerd) what about .posixPermissions, .referenceCount, .systemNumber, .systemFileNumber, .ownerAccountName, .groupOwnerAccountName, .type, .immuatable, .appendOnly, .ownerAccountID, .groupOwnerAccountID
880-
#else
881-
882874
#if os(Linux)
883875
let (s, creationDate) = try _statxFile(atPath: path)
884876
result[.creationDate] = creationDate
@@ -892,29 +884,36 @@ open class FileManager : NSObject {
892884
let ti = (TimeInterval(s.st_mtimespec.tv_sec) - kCFAbsoluteTimeIntervalSince1970) + (1.0e-9 * TimeInterval(s.st_mtimespec.tv_nsec))
893885
#elseif os(Android)
894886
let ti = (TimeInterval(s.st_mtime) - kCFAbsoluteTimeIntervalSince1970) + (1.0e-9 * TimeInterval(s.st_mtime_nsec))
887+
#elseif os(Windows)
888+
let ti = (TimeInterval(s.st_mtime) - kCFAbsoluteTimeIntervalSince1970)
895889
#else
896890
let ti = (TimeInterval(s.st_mtim.tv_sec) - kCFAbsoluteTimeIntervalSince1970) + (1.0e-9 * TimeInterval(s.st_mtim.tv_nsec))
897891
#endif
898892
result[.modificationDate] = Date(timeIntervalSinceReferenceDate: ti)
899-
900-
result[.posixPermissions] = NSNumber(value: UInt64(s.st_mode & ~S_IFMT))
893+
894+
result[.posixPermissions] = NSNumber(value: _filePermissionsMask(mode: UInt32(s.st_mode)))
901895
result[.referenceCount] = NSNumber(value: UInt64(s.st_nlink))
902896
result[.systemNumber] = NSNumber(value: UInt64(s.st_dev))
903897
result[.systemFileNumber] = NSNumber(value: UInt64(s.st_ino))
904-
898+
899+
#if os(Windows)
900+
result[.deviceIdentifier] = NSNumber(value: UInt64(s.st_rdev))
901+
let type = FileAttributeType(attributes: try windowsFileAttributes(atPath: path))
902+
#else
905903
if let pwd = getpwuid(s.st_uid), pwd.pointee.pw_name != nil {
906904
let name = String(cString: pwd.pointee.pw_name)
907905
result[.ownerAccountName] = name
908906
}
909-
907+
910908
if let grd = getgrgid(s.st_gid), grd.pointee.gr_name != nil {
911909
let name = String(cString: grd.pointee.gr_name)
912910
result[.groupOwnerAccountName] = name
913911
}
914912

915913
let type = FileAttributeType(statMode: s.st_mode)
914+
#endif
916915
result[.type] = type
917-
916+
918917
if type == .typeBlockSpecial || type == .typeCharacterSpecial {
919918
result[.deviceIdentifier] = NSNumber(value: UInt64(s.st_rdev))
920919
}
@@ -929,11 +928,10 @@ open class FileManager : NSObject {
929928
#endif
930929
result[.ownerAccountID] = NSNumber(value: UInt64(s.st_uid))
931930
result[.groupOwnerAccountID] = NSNumber(value: UInt64(s.st_gid))
932-
#endif
933931

934932
return result
935933
}
936-
934+
937935
/* attributesOfFileSystemForPath:error: returns an NSDictionary of key/value pairs containing the attributes of the filesystem containing the provided path. If this method returns 'nil', an NSError will be returned by reference in the 'error' parameter. This method does not traverse a terminal symlink.
938936

939937
This method replaces fileSystemAttributesAtPath:.
@@ -1870,15 +1868,21 @@ open class FileManager : NSObject {
18701868
return statInfo
18711869
}
18721870

1873-
internal func _permissionsOfItem(atPath path: String) throws -> Int {
1874-
let fileInfo = try _lstatFile(atPath: path)
1871+
internal func _filePermissionsMask(mode : UInt32) -> Int {
18751872
#if os(Windows)
1876-
return Int(fileInfo.st_mode & ~UInt16(ucrt.S_IFMT))
1873+
return Int(mode & ~UInt32(ucrt.S_IFMT))
1874+
#elseif canImport(Darwin)
1875+
return Int(mode & ~UInt32(S_IFMT))
18771876
#else
1878-
return Int(fileInfo.st_mode & ~S_IFMT)
1877+
return Int(mode & ~S_IFMT)
18791878
#endif
18801879
}
18811880

1881+
internal func _permissionsOfItem(atPath path: String) throws -> Int {
1882+
let fileInfo = try _lstatFile(atPath: path)
1883+
return _filePermissionsMask(mode: UInt32(fileInfo.st_mode))
1884+
}
1885+
18821886

18831887
#if os(Linux)
18841888
// statx() is only supported by Linux kernels >= 4.11.0

0 commit comments

Comments
 (0)