summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Hai Zhang <zhanghai@google.com> 2020-05-19 22:00:18 -0700
committer Hai Zhang <zhanghai@google.com> 2020-05-20 12:08:41 -0700
commitcf2ee87fd43aaacd8e952fc9bc116fd27f2d8eb7 (patch)
tree059a5d85c1ca664cede60237723ffcc5717c090c
parent25adf3c4718092df863d3173c5066f705a04ce49 (diff)
Maintain compatibility by deleting target directory before renaming into it.
The target shouldn't be a directory, but if it is, it would be deleted (as long as it's empty). This became some kind of API and we need to remain compatible with it. Bug: 151959443 Test: Reboot and ensure ShortcutService can persist its state Change-Id: I11a80cd4252128b025912b7aab86b113935e549a Merged-In: I11a80cd4252128b025912b7aab86b113935e549a
-rw-r--r--core/java/android/util/AtomicFile.java31
1 files changed, 20 insertions, 11 deletions
diff --git a/core/java/android/util/AtomicFile.java b/core/java/android/util/AtomicFile.java
index 1dd4cbb403db..4d2c9b5f5df7 100644
--- a/core/java/android/util/AtomicFile.java
+++ b/core/java/android/util/AtomicFile.java
@@ -116,10 +116,7 @@ public class AtomicFile {
mStartTime = startTime;
if (mLegacyBackupName.exists()) {
- if (!mLegacyBackupName.renameTo(mBaseName)) {
- Log.e(LOG_TAG, "Failed to rename legacy backup file " + mLegacyBackupName
- + " to base file " + mBaseName);
- }
+ rename(mLegacyBackupName, mBaseName);
}
try {
@@ -157,9 +154,7 @@ public class AtomicFile {
} catch (IOException e) {
Log.e(LOG_TAG, "Failed to close file output stream", e);
}
- if (!mNewName.renameTo(mBaseName)) {
- Log.e(LOG_TAG, "Failed to rename new file " + mNewName + " to base file " + mBaseName);
- }
+ rename(mNewName, mBaseName);
if (mCommitTag != null) {
com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
mCommitTag, SystemClock.uptimeMillis() - mStartTime);
@@ -221,10 +216,7 @@ public class AtomicFile {
*/
public FileInputStream openRead() throws FileNotFoundException {
if (mLegacyBackupName.exists()) {
- if (!mLegacyBackupName.renameTo(mBaseName)) {
- Log.e(LOG_TAG, "Failed to rename legacy backup file " + mLegacyBackupName
- + " to base file " + mBaseName);
- }
+ rename(mLegacyBackupName, mBaseName);
}
// Don't delete mNewName here - it was okay to call openRead() between startWrite() and
@@ -301,4 +293,21 @@ public class AtomicFile {
IoUtils.closeQuietly(out);
}
}
+
+ private static void rename(File source, File target) {
+ // We used to delete the target file before rename, but that isn't atomic, and the rename()
+ // syscall should atomically replace the target file. However in the case where the target
+ // file is a directory, a simple rename() won't work. We need to delete the file in this
+ // case because there are callers who erroneously called mBaseName.mkdirs() (instead of
+ // mBaseName.getParentFile().mkdirs()) before creating the AtomicFile, and it worked
+ // regardless, so this deletion became some kind of API.
+ if (target.isDirectory()) {
+ if (!target.delete()) {
+ Log.e(LOG_TAG, "Failed to delete file which is a directory " + target);
+ }
+ }
+ if (!source.renameTo(target)) {
+ Log.e(LOG_TAG, "Failed to rename " + source + " to " + target);
+ }
+ }
}