@@ -82,16 +82,18 @@ internal class CapacityReader: Reader<Disks> {
8282 if let d = self . list. first ( where: { $0. BSDName == BSDName} ) , let idx = self . list. index ( where: { $0. BSDName == BSDName} ) {
8383 if d. removable && !removableState {
8484 if d. parent != 0 { IOObjectRelease ( d. parent) }
85+ if let path = d. path { self . purgableSpace. removeValue ( forKey: path) }
8586 self . list. remove ( at: idx)
8687 continue
8788 }
8889
8990 if driveIdentityChanged ( d, url, disk) {
9091 if d. parent != 0 { IOObjectRelease ( d. parent) }
92+ if let path = d. path { self . purgableSpace. removeValue ( forKey: path) }
9193 self . list. remove ( at: idx)
9294 } else {
9395 if let path = d. path {
94- self . list. updateFreeSize ( idx, newValue: self . freeDiskSpaceInBytes ( path) )
96+ self . list. updateFreeSize ( idx, newValue: self . diskSpaceInBytes ( path, fileSystem : d . fileSystem ) . free )
9597 self . list. updateSMARTData ( idx, smart: self . getSMARTDetails ( for: BSDName) )
9698 }
9799 continue
@@ -100,8 +102,9 @@ internal class CapacityReader: Reader<Disks> {
100102
101103 if var d = driveDetails ( disk, removableState: removableState) {
102104 if let path = d. path {
103- d. free = self . freeDiskSpaceInBytes ( path)
104- d. size = self . totalDiskSpaceInBytes ( path)
105+ let space = self . diskSpaceInBytes ( path, fileSystem: d. fileSystem)
106+ d. free = space. free
107+ d. size = space. total
105108 }
106109 d. smart = self . getSMARTDetails ( for: BSDName)
107110 guard d. size != 0 else {
@@ -118,71 +121,63 @@ internal class CapacityReader: Reader<Disks> {
118121
119122 active. difference ( from: self . list. map { $0. BSDName } ) . forEach { ( BSDName: String ) in
120123 if let idx = self . list. index ( where: { $0. BSDName == BSDName } ) {
121- let parent = self . list. array [ idx] . parent
122- if parent != 0 { IOObjectRelease ( parent) }
124+ let d = self . list. array [ idx]
125+ if d. parent != 0 { IOObjectRelease ( d. parent) }
126+ if let path = d. path { self . purgableSpace. removeValue ( forKey: path) }
123127 self . list. remove ( at: idx)
124128 }
125129 }
126130
127131 self . callback ( self . list)
128132
129133 }
130- private func freeDiskSpaceInBytes ( _ path: URL ) -> Int64 {
134+ private func diskSpaceInBytes ( _ path: URL , fileSystem : String ) -> ( total : Int64 , free : Int64 ) {
131135 var path = path
132136 path. removeAllCachedResourceValues ( )
133137
134138 var stat = statfs ( )
135139 if statfs ( path. path, & stat) == 0 {
136140 let total = Int64 ( stat. f_blocks) * Int64( stat. f_bsize)
137- let free = Int64 ( stat. f_bfree ) * Int64( stat. f_bsize)
138- let used = total - free
141+ let available = Int64 ( stat. f_bavail ) * Int64( stat. f_bsize)
142+ let used = total - available
139143
140144 var purgeable : Int64 = 0
141- if let pair = self . purgableSpace [ path] , Date ( ) . timeIntervalSince ( pair. 0 ) <= 30 {
142- purgeable = pair. 1
143- } else {
144- let value = CSDiskSpaceGetRecoveryEstimate ( path as NSURL )
145- if used > 0 && value <= UInt64 ( used) {
146- purgeable = Int64 ( value)
145+ if fileSystem == " apfs " {
146+ if let pair = self . purgableSpace [ path] , Date ( ) . timeIntervalSince ( pair. 0 ) <= 60 {
147+ purgeable = pair. 1
148+ } else {
149+ let value = CSDiskSpaceGetRecoveryEstimate ( path as NSURL )
150+ if used > 0 && value <= UInt64 ( used) {
151+ purgeable = Int64 ( value)
152+ }
153+ self . purgableSpace [ path] = ( Date ( ) , purgeable)
147154 }
148- self . purgableSpace [ path] = ( Date ( ) , purgeable)
149155 }
150156
151- return free + purgeable
157+ return ( total , available + purgeable)
152158 }
153159
154- do {
155- let values = try path. resourceValues ( forKeys: [ . volumeAvailableCapacityForImportantUsageKey] )
156- if let capacity = values. volumeAvailableCapacityForImportantUsage, capacity != 0 {
157- return capacity
158- }
159- } catch let err {
160- error ( " error retrieving free space #1: \( err. localizedDescription) " , log: self . log)
161- }
160+ var total : Int64 = 0
161+ var free : Int64 = 0
162162
163163 do {
164164 let systemAttributes = try FileManager . default. attributesOfFileSystem ( forPath: path. path)
165- if let freeSpace = ( systemAttributes [ FileAttributeKey . systemFreeSize] as? NSNumber ) ? . int64Value {
166- return freeSpace
167- }
165+ total = ( systemAttributes [ FileAttributeKey . systemSize] as? NSNumber ) ? . int64Value ?? 0
166+ free = ( systemAttributes [ FileAttributeKey . systemFreeSize] as? NSNumber ) ? . int64Value ?? 0
168167 } catch let err {
169- error ( " error retrieving free space: \( err. localizedDescription) " , log: self . log)
168+ error ( " error retrieving disk space: \( err. localizedDescription) " , log: self . log)
170169 }
171170
172- return 0
173- }
174-
175- private func totalDiskSpaceInBytes( _ path: URL ) -> Int64 {
176171 do {
177- let systemAttributes = try FileManager . default . attributesOfFileSystem ( forPath : path . path )
178- if let totalSpace = ( systemAttributes [ FileAttributeKey . systemSize ] as? NSNumber ) ? . int64Value {
179- return totalSpace
172+ let values = try path . resourceValues ( forKeys : [ . volumeAvailableCapacityForImportantUsageKey ] )
173+ if let capacity = values . volumeAvailableCapacityForImportantUsage , capacity != 0 {
174+ free = capacity
180175 }
181176 } catch let err {
182- error ( " error retrieving total space: \( err. localizedDescription) " , log: self . log)
177+ error ( " error retrieving free space: \( err. localizedDescription) " , log: self . log)
183178 }
184179
185- return 0
180+ return ( total , free )
186181 }
187182
188183 private func getSMARTDetails( for BSDName: String ) -> smart_t ? {
@@ -402,7 +397,7 @@ internal class CapacityReader: Reader<Disks> {
402397 let totalWritten = deviceWritten ?? self . smartTotals [ BSDName] ? . written ?? Int64 ( rawValue ( 241 ) ?? 0 ) * bytesPerLBA
403398
404399 let errorCounts = [ rawValue ( 5 ) , rawValue ( 197 ) , rawValue ( 198 ) ] . compactMap ( { $0 } )
405-
400+
406401 return smart_t (
407402 temperature: temperature,
408403 life: life,
0 commit comments