fix(spoof): preserve [pkg] sections in atomicWrite

atomicWrite previously overwrote the entire security_patch.txt
with only the three global lines, destroying the per-package
[pkg] overrides supported by ConfigurationManager. Read the
existing file, strip only global system/boot/vendor/all key
assignments, prepend the refreshed global block, and append
everything else (comments, blanks, all [pkg] sections) verbatim.
This commit is contained in:
Enginex0
2026-05-19 05:09:39 +01:00
parent c511cc48e9
commit 4e55ba4e77
@@ -19,6 +19,8 @@ object PatchLevelManager {
private val DATE_PATTERN = Regex("^\\d{4}-\\d{2}-\\d{2}$")
private val PROP_PATTERN = Regex("^SECURITY_PATCH=(.+)$", RegexOption.MULTILINE)
private val SECTION_HEADER = Regex("^\\[[a-zA-Z0-9_.-]+]$")
private val GLOBAL_KEYS = setOf("system", "boot", "vendor", "all")
private val PIF_SOURCES =
listOf(
@@ -107,7 +109,7 @@ object PatchLevelManager {
private fun atomicWrite(date: String) {
val target = File(PATCH_FILE)
val staging = File(STAGING_FILE)
staging.writeText("system=$date\nboot=$date\nvendor=$date\n")
staging.writeText(mergedContents(target, date))
Files.move(
staging.toPath(),
target.toPath(),
@@ -115,4 +117,36 @@ object PatchLevelManager {
StandardCopyOption.REPLACE_EXISTING,
)
}
private fun mergedContents(target: File, date: String): String {
val globalBlock = "system=$date\nboot=$date\nvendor=$date\n"
if (!target.exists()) return globalBlock
val tail =
runCatching { stripGlobalAssignments(target.readLines()) }.getOrNull()
?: return globalBlock
if (tail.isEmpty()) return globalBlock
return globalBlock + tail.joinToString("\n", prefix = "\n", postfix = "\n")
}
private fun stripGlobalAssignments(lines: List<String>): List<String> {
val kept = mutableListOf<String>()
var inGlobal = true
for (line in lines) {
val trimmed = line.trim()
if (SECTION_HEADER.matches(trimmed)) {
inGlobal = false
kept += line
continue
}
if (inGlobal && isGlobalKeyAssignment(trimmed)) continue
kept += line
}
return kept
}
private fun isGlobalKeyAssignment(trimmed: String): Boolean {
if (trimmed.isEmpty() || trimmed.startsWith("#")) return false
val key = trimmed.substringBefore("=").trim().lowercase()
return key in GLOBAL_KEYS
}
}