From fa6d439a785593a47d4b236c20cd133efd3fbe8c Mon Sep 17 00:00:00 2001 From: Manjeet Rulhania Date: Mon, 20 Mar 2023 17:13:58 -0700 Subject: [PATCH] Add backup/reserved files in new permission subsystem Bug: 274484493 Test: build Change-Id: Ida3516c1730755a6bf3e636b8818726157c40831 --- .../permission/access/AccessPersistence.kt | 8 ++-- .../access/util/AtomicFileExtensions.kt | 43 +++++++++++++++++-- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/services/permission/java/com/android/server/permission/access/AccessPersistence.kt b/services/permission/java/com/android/server/permission/access/AccessPersistence.kt index 5b1e4efe5acd9..4182ecf2666d7 100644 --- a/services/permission/java/com/android/server/permission/access/AccessPersistence.kt +++ b/services/permission/java/com/android/server/permission/access/AccessPersistence.kt @@ -30,9 +30,9 @@ import com.android.modules.utils.BinaryXmlSerializer import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.util.PermissionApex import com.android.server.permission.access.util.parseBinaryXml -import com.android.server.permission.access.util.read +import com.android.server.permission.access.util.readWithReserveCopy import com.android.server.permission.access.util.serializeBinaryXml -import com.android.server.permission.access.util.writeInlined +import com.android.server.permission.access.util.writeWithReserveCopy import java.io.File import java.io.FileNotFoundException @@ -100,7 +100,7 @@ class AccessPersistence( */ private inline fun File.parse(block: BinaryXmlPullParser.() -> Unit): Boolean = try { - AtomicFile(this).read { it.parseBinaryXml(block) } + AtomicFile(this).readWithReserveCopy { it.parseBinaryXml(block) } true } catch (e: FileNotFoundException) { Log.i(LOG_TAG, "$this not found") @@ -179,7 +179,7 @@ class AccessPersistence( private inline fun File.serialize(block: BinaryXmlSerializer.() -> Unit) { try { - AtomicFile(this).writeInlined { it.serializeBinaryXml(block) } + AtomicFile(this).writeWithReserveCopy { it.serializeBinaryXml(block) } } catch (e: Exception) { Log.e(LOG_TAG, "Failed to serialize $this", e) } diff --git a/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt b/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt index 984dfb5a7548b..2c29332a638b1 100644 --- a/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt +++ b/services/permission/java/com/android/server/permission/access/util/AtomicFileExtensions.kt @@ -16,17 +16,54 @@ package com.android.server.permission.access.util +import android.os.FileUtils import android.util.AtomicFile +import android.util.Log +import java.io.File import java.io.FileInputStream +import java.io.FileNotFoundException import java.io.FileOutputStream import java.io.IOException /** - * Read from an [AtomicFile] and close everything safely when done. + * Read from an [AtomicFile], fallback to reserve file to read the data. + */ +@Throws(Exception::class) +inline fun AtomicFile.readWithReserveCopy(block: (FileInputStream) -> Unit) { + try { + openRead().use(block) + } catch (e: FileNotFoundException) { + throw e + } catch (e: Exception) { + Log.wtf("AccessPersistence", "Failed to read $this", e) + val reserveFile = File(baseFile.parentFile, baseFile.name + ".reservecopy") + try { + AtomicFile(reserveFile).openRead().use(block) + } catch (e2: Exception) { + Log.e("AccessPersistence", "Failed to read $reserveFile", e2) + throw e + } + } +} + +/** + * Write to actual file and reserve file. */ @Throws(IOException::class) -inline fun AtomicFile.read(block: (FileInputStream) -> Unit) { - openRead().use(block) +inline fun AtomicFile.writeWithReserveCopy(block: (FileOutputStream) -> Unit) { + val reserveFile = File(baseFile.parentFile, baseFile.name + ".reservecopy") + reserveFile.delete() + writeInlined(block) + try { + FileInputStream(baseFile).use { inputStream -> + FileOutputStream(reserveFile).use { outputStream -> + FileUtils.copy(inputStream, outputStream) + outputStream.fd.sync() + } + } + } catch (e: Exception) { + Log.e("AccessPersistence", "Failed to write $reserveFile", e) + } } /**