field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

TeraMediaProcessUse.swift (2905B)


      1 import Darwin
      2 import Foundation
      3 import RadrootsKit
      4 
      5 /// Records admission before underlying work can outlive a caller or runtime.
      6 /// The marker deliberately survives shutdown, cancellation and failed creation.
      7 /// It is local coordination evidence, never a portable ownership database.
      8 enum TeraMediaProcessUse {
      9   static let directory = ".tera_media_use"
     10 
     11   static func admit(applicationSupportDirectory: String) throws -> RadrootsFileUseReservation {
     12     let parts = applicationSupportDirectory.split(separator: "/")
     13     guard applicationSupportDirectory.hasPrefix("/"), !applicationSupportDirectory.utf8.contains(0),
     14       !parts.isEmpty, parts.allSatisfy({ $0 != "." && $0 != ".." })
     15     else { throw RadrootsAppleFileError.invalidRequest }
     16     return try admit(root: URL(fileURLWithPath: applicationSupportDirectory, isDirectory: true))
     17   }
     18 
     19   static func admit(root: URL) throws -> RadrootsFileUseReservation {
     20     guard let use = try RadrootsAppleFileMaintenance(root: root).reserveUse() else {
     21       throw RadrootsAppleFileError.transientFailure
     22     }
     23     let roots = try RadrootsAppleFileRoots(
     24       appIdentifier: "tera.media.use", dataRoot: root, cacheRoot: root, temporaryRoot: root
     25     )
     26     let pid = getpid()
     27     let file = RadrootsFileReference(scope: .data, relativePath: "\(directory)/\(pid)")
     28     try RadrootsAppleFileAccess(roots: roots).write(.inline(Data("tera.media.use.v1 \(pid)\n".utf8)), to: file)
     29     try use.validate()
     30     return use
     31   }
     32 
     33   /// Must be called under the exclusive reservation. ESRCH is the only admitted
     34   /// absence observation. PID reuse and permission failures conservatively retain.
     35   static func hasNoLiveUsers(
     36     roots: RadrootsAppleFileRoots,
     37     scan: RadrootsFileMaintenanceScan,
     38     remaining: inout Int,
     39     isAbsent: (Int32) -> Bool = definitelyAbsent
     40   ) throws -> Bool {
     41     let access = RadrootsAppleFileAccess(roots: roots)
     42     while remaining > 0 {
     43       let page = try scan.next(limit: min(64, remaining))
     44       remaining -= page.scannedEntries
     45       for entry in page.entries {
     46         guard entry.kind == .regularFile, entry.sizeBytes > 0, entry.sizeBytes <= 64,
     47           let pid = Int32(entry.name), pid > 0, String(pid) == entry.name
     48         else { return false }
     49         let file = RadrootsFileReference(scope: .data, relativePath: "\(directory)/\(entry.name)")
     50         guard case let .inline(data) = try access.read(file, mode: .inline(maxBytes: 64)),
     51           data == Data("tera.media.use.v1 \(pid)\n".utf8), isAbsent(pid)
     52         else { return false }
     53         // Never reuse a marker after a conditional-unlink identity mismatch.
     54         guard try scan.remove(entry) else { return false }
     55       }
     56       if page.reachedEnd {
     57         return true
     58       }
     59     }
     60     return false
     61   }
     62 
     63   private static func definitelyAbsent(_ pid: Int32) -> Bool {
     64     let result = Darwin.kill(pid, 0)
     65     return result == -1 && errno == ESRCH
     66   }
     67 }