aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2017-09-27 21:19:24 +0000
committerRui Ueyama <ruiu@google.com>2017-09-27 21:19:24 +0000
commitde8eb76ebd7a32e09c8d416996d468d88707ca3e (patch)
treed2e596d9885a7eb2ae48d1a50d66a380ff342d47
parent22a815a49ac75baa6d227c96ad812dcb863ab029 (diff)
Do not remove a target file in FileOutputBuffer::create().
FileOutputBuffer::create() attempts to remove a target file if the file is a regular one, which results in an unexpected result in a failure scenario. If something goes wrong and the user of FileOutputBuffer decides to not call commit(), it leaves nothing. An existing file is removed, and no new file is created. What we should do is to atomically replace an existing file with a new file using rename(), so that it wouldn't remove an existing file without creating a new one. Differential Revision: https://reviews.llvm.org/D38283 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314345 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Support/FileOutputBuffer.cpp9
1 files changed, 1 insertions, 8 deletions
diff --git a/lib/Support/FileOutputBuffer.cpp b/lib/Support/FileOutputBuffer.cpp
index 731740d012d..d9c9f8234e2 100644
--- a/lib/Support/FileOutputBuffer.cpp
+++ b/lib/Support/FileOutputBuffer.cpp
@@ -65,13 +65,6 @@ FileOutputBuffer::create(StringRef FilePath, size_t Size, unsigned Flags) {
IsRegular = false;
}
- if (IsRegular) {
- // Delete target file.
- EC = sys::fs::remove(FilePath);
- if (EC)
- return EC;
- }
-
SmallString<128> TempFilePath;
int FD;
if (IsRegular) {
@@ -125,7 +118,7 @@ std::error_code FileOutputBuffer::commit() {
std::error_code EC;
if (IsRegular) {
- // Rename file to final name.
+ // Atomically replace the existing file with the new one.
EC = sys::fs::rename(Twine(TempPath), Twine(FinalPath));
sys::DontRemoveFileOnSignal(TempPath);
} else {