1 /*
<lambda>null2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.server.permission.access.util
18
19 import android.os.FileUtils
20 import android.util.AtomicFile
21 import android.util.Slog
22 import com.android.server.security.FileIntegrity;
23 import java.io.File
24 import java.io.FileInputStream
25 import java.io.FileNotFoundException
26 import java.io.FileOutputStream
27 import java.io.IOException
28
29 /** Read from an [AtomicFile], fallback to reserve file to read the data. */
30 @Throws(Exception::class)
readWithReserveCopynull31 inline fun AtomicFile.readWithReserveCopy(block: (FileInputStream) -> Unit) {
32 try {
33 openRead().use(block)
34 } catch (e: FileNotFoundException) {
35 throw e
36 } catch (e: Exception) {
37 Slog.wtf("AccessPersistence", "Failed to read $this", e)
38 val reserveFile = File(baseFile.parentFile, baseFile.name + ".reservecopy")
39 try {
40 AtomicFile(reserveFile).openRead().use(block)
41 } catch (e2: Exception) {
42 Slog.e("AccessPersistence", "Failed to read $reserveFile", e2)
43 throw e
44 }
45 }
46 }
47
48 /** Write to actual file and reserve file. */
49 @Throws(IOException::class)
writeWithReserveCopynull50 inline fun AtomicFile.writeWithReserveCopy(block: (FileOutputStream) -> Unit) {
51 writeInlined(block)
52 val reserveFile = File(baseFile.parentFile, baseFile.name + ".reservecopy")
53 reserveFile.delete()
54 try {
55 FileInputStream(baseFile).use { inputStream ->
56 FileOutputStream(reserveFile).use { outputStream ->
57 FileUtils.copy(inputStream, outputStream)
58 outputStream.fd.sync()
59 }
60 }
61 } catch (e: Exception) {
62 Slog.e("AccessPersistence", "Failed to write $reserveFile", e)
63 }
64 try {
65 FileIntegrity.setUpFsVerity(baseFile)
66 FileIntegrity.setUpFsVerity(reserveFile)
67 } catch (e: Exception) {
68 Slog.e("AccessPersistence", "Failed to verity-protect runtime-permissions", e)
69 }
70 }
71
72 /** Write to an [AtomicFile] and close everything safely when done. */
73 @Throws(IOException::class)
74 // Renamed to writeInlined() to avoid conflict with the hidden AtomicFile.write() that isn't inline.
writeInlinednull75 inline fun AtomicFile.writeInlined(block: (FileOutputStream) -> Unit) {
76 startWrite().use {
77 try {
78 block(it)
79 finishWrite(it)
80 } catch (t: Throwable) {
81 failWrite(it)
82 throw t
83 }
84 }
85 }
86