add astra draft
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import Darwin
|
||||
import FamilyControls
|
||||
import Foundation
|
||||
import PolicyCore
|
||||
|
||||
struct NativeState: Codable {
|
||||
var snapshot: Snapshot?
|
||||
var selection = FamilyActivitySelection()
|
||||
var selectionRevision = UUID().uuidString
|
||||
var observation = Observation()
|
||||
var generation: String?
|
||||
var policyKey: String?
|
||||
var thresholds: [Int] = []
|
||||
var monitoringReady = false
|
||||
var shielded = false
|
||||
var lastEvent = "Not configured"
|
||||
var monitoringError: String?
|
||||
}
|
||||
|
||||
enum LocalError: LocalizedError {
|
||||
case message(String)
|
||||
var errorDescription: String? {
|
||||
switch self { case .message(let value): return value }
|
||||
}
|
||||
}
|
||||
|
||||
enum StateStore {
|
||||
/// A process-wide UserDefaults cache is not sufficient: the app and extension both write.
|
||||
/// Lock one file while atomically replacing another. Corrupt state is never reset to defaults.
|
||||
static func withState<T>(_ operation: (inout NativeState) throws -> T) throws -> T {
|
||||
guard let group = Bundle.main.object(forInfoDictionaryKey: "APCAppGroup") as? String,
|
||||
let directory = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: group) else {
|
||||
throw LocalError.message("App Group unavailable. Check signing and APC_APP_GROUP on all targets.")
|
||||
}
|
||||
let lockPath = directory.appendingPathComponent("state.lock").path
|
||||
let fd = open(lockPath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)
|
||||
guard fd >= 0 else { throw LocalError.message("Cannot open the shared-state lock") }
|
||||
defer { close(fd) }
|
||||
guard flock(fd, LOCK_EX) == 0 else { throw LocalError.message("Cannot lock shared state") }
|
||||
defer { flock(fd, LOCK_UN) }
|
||||
let file = directory.appendingPathComponent("state.json")
|
||||
var state = NativeState()
|
||||
if FileManager.default.fileExists(atPath: file.path) {
|
||||
state = try WireCoding.decoder().decode(NativeState.self, from: Data(contentsOf: file))
|
||||
}
|
||||
let result = try operation(&state)
|
||||
try WireCoding.encoder().encode(state).write(to: file, options: .atomic)
|
||||
try FileManager.default.setAttributes(
|
||||
[.protectionKey: FileProtectionType.completeUntilFirstUserAuthentication], atPath: file.path
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user