Skip to content

Commit ece9521

Browse files
authored
Merge pull request #1250 from amosavian/filemgr/fsattributes
2 parents 93b05b9 + 5a08c22 commit ece9521

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

Foundation/FileManager.swift

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,34 @@ open class FileManager : NSObject {
343343
This method replaces fileSystemAttributesAtPath:.
344344
*/
345345
open func attributesOfFileSystem(forPath path: String) throws -> [FileAttributeKey : Any] {
346-
NSUnimplemented()
346+
// statvfs(2) doesn't support 64bit inode on Darwin (apfs), fallback to statfs(2)
347+
#if os(OSX) || os(iOS)
348+
var s = statfs()
349+
guard statfs(path, &s) == 0 else {
350+
throw _NSErrorWithErrno(errno, reading: true, path: path)
351+
}
352+
#else
353+
var s = statvfs()
354+
guard statvfs(path, &s) == 0 else {
355+
throw _NSErrorWithErrno(errno, reading: true, path: path)
356+
}
357+
#endif
358+
359+
360+
var result = [FileAttributeKey : Any]()
361+
#if os(OSX) || os(iOS)
362+
let blockSize = UInt64(s.f_bsize)
363+
result[.systemNumber] = NSNumber(value: UInt64(s.f_fsid.val.0))
364+
#else
365+
let blockSize = UInt64(s.f_frsize)
366+
result[.systemNumber] = NSNumber(value: UInt64(s.f_fsid))
367+
#endif
368+
result[.systemSize] = NSNumber(value: blockSize * UInt64(s.f_blocks))
369+
result[.systemFreeSize] = NSNumber(value: blockSize * UInt64(s.f_bavail))
370+
result[.systemNodes] = NSNumber(value: UInt64(s.f_files))
371+
result[.systemFreeNodes] = NSNumber(value: UInt64(s.f_ffree))
372+
373+
return result
347374
}
348375

349376
/* createSymbolicLinkAtPath:withDestination:error: returns YES if the symbolic link that point at 'destPath' was able to be created at the location specified by 'path'. If this method returns NO, the link was unable to be created and an NSError will be returned by reference in the 'error' parameter. This method does not traverse a terminal symlink.

TestFoundation/TestFileManager.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class TestFileManager : XCTestCase {
2424
("test_moveFile", test_moveFile),
2525
("test_fileSystemRepresentation", test_fileSystemRepresentation),
2626
("test_fileAttributes", test_fileAttributes),
27+
("test_fileSystemAttributes", test_fileSystemAttributes),
2728
("test_setFileAttributes", test_setFileAttributes),
2829
("test_directoryEnumerator", test_directoryEnumerator),
2930
("test_pathEnumerator",test_pathEnumerator),
@@ -206,6 +207,40 @@ class TestFileManager : XCTestCase {
206207
}
207208
}
208209

210+
func test_fileSystemAttributes() {
211+
let fm = FileManager.default
212+
let path = NSTemporaryDirectory()
213+
214+
do {
215+
let attrs = try fm.attributesOfFileSystem(forPath: path)
216+
217+
XCTAssertTrue(attrs.count > 0)
218+
219+
let systemNumber = attrs[.systemNumber] as? NSNumber
220+
XCTAssertNotNil(systemNumber)
221+
XCTAssertNotEqual(systemNumber!.uint64Value, 0)
222+
223+
let systemFreeSize = attrs[.systemFreeSize] as? NSNumber
224+
XCTAssertNotNil(systemFreeSize)
225+
XCTAssertNotEqual(systemFreeSize!.uint64Value, 0)
226+
227+
let systemSize = attrs[.systemSize] as? NSNumber
228+
XCTAssertNotNil(systemSize)
229+
XCTAssertGreaterThan(systemSize!.uint64Value, systemFreeSize!.uint64Value)
230+
231+
let systemFreeNodes = attrs[.systemFreeNodes] as? NSNumber
232+
XCTAssertNotNil(systemFreeNodes)
233+
XCTAssertNotEqual(systemFreeNodes!.uint64Value, 0)
234+
235+
let systemNodes = attrs[.systemNodes] as? NSNumber
236+
XCTAssertNotNil(systemNodes)
237+
XCTAssertGreaterThan(systemNodes!.uint64Value, systemFreeNodes!.uint64Value)
238+
239+
} catch let err {
240+
XCTFail("\(err)")
241+
}
242+
}
243+
209244
func test_setFileAttributes() {
210245
let path = NSTemporaryDirectory() + "test_setFileAttributes\(NSUUID().uuidString)"
211246
let fm = FileManager.default

0 commit comments

Comments
 (0)