RadrootsFileCapacity.swift (1293B)
1 import Darwin 2 import Foundation 3 4 /// App-owned file write admission only. Capacity stays on device and is never 5 /// telemetry. This is a conservative preflight, not a reservation: write/sync 6 /// still classify actual ENOSPC and EDQUOT and preserve ambiguous outcomes. 7 enum RadrootsFileCapacity { 8 static func require(_ bytes: Int, on descriptor: Int32) throws { 9 guard bytes >= 0 else { throw RadrootsAppleFileError.invalidRequest } 10 var volume = statfs() 11 guard Darwin.fstatfs(descriptor, &volume) == 0 else { 12 throw RadrootsAppleFileError.posix(errno) 13 } 14 guard volume.f_bsize > 0 else { throw RadrootsAppleFileError.permanentFailure } 15 guard admits(UInt64(bytes), availableBlocks: volume.f_bavail, blockSize: UInt64(volume.f_bsize)) else { 16 throw RadrootsAppleFileError.spaceInsufficient 17 } 18 } 19 20 static func admits(_ bytes: UInt64, availableBlocks: UInt64, blockSize: UInt64) -> Bool { 21 guard blockSize > 0 else { return false } 22 // Compare blocks without multiplying filesystem counters or rounding 23 // bytes upward with an addition that could overflow UInt64. 24 let required = bytes / blockSize + (bytes % blockSize == 0 ? 0 : 1) 25 return availableBlocks >= required 26 } 27 }