diff options
Diffstat (limited to 'lib/Support/FileUtilities.cpp')
-rw-r--r-- | lib/Support/FileUtilities.cpp | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/lib/Support/FileUtilities.cpp b/lib/Support/FileUtilities.cpp index 62eb7bfda195..d11fbb54dc0d 100644 --- a/lib/Support/FileUtilities.cpp +++ b/lib/Support/FileUtilities.cpp @@ -12,9 +12,12 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/FileUtilities.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include <cctype> #include <cmath> @@ -264,3 +267,66 @@ int llvm::DiffFilesWithTolerance(StringRef NameA, return CompareFailed; } + +void llvm::AtomicFileWriteError::log(raw_ostream &OS) const { + OS << "atomic_write_error: "; + switch (Error) { + case atomic_write_error::failed_to_create_uniq_file: + OS << "failed_to_create_uniq_file"; + return; + case atomic_write_error::output_stream_error: + OS << "output_stream_error"; + return; + case atomic_write_error::failed_to_rename_temp_file: + OS << "failed_to_rename_temp_file"; + return; + } + llvm_unreachable("unknown atomic_write_error value in " + "failed_to_rename_temp_file::log()"); +} + +llvm::Error llvm::writeFileAtomically(StringRef TempPathModel, + StringRef FinalPath, StringRef Buffer) { + return writeFileAtomically(TempPathModel, FinalPath, + [&Buffer](llvm::raw_ostream &OS) { + OS.write(Buffer.data(), Buffer.size()); + return llvm::Error::success(); + }); +} + +llvm::Error llvm::writeFileAtomically( + StringRef TempPathModel, StringRef FinalPath, + std::function<llvm::Error(llvm::raw_ostream &)> Writer) { + SmallString<128> GeneratedUniqPath; + int TempFD; + if (sys::fs::createUniqueFile(TempPathModel.str(), TempFD, + GeneratedUniqPath)) { + return llvm::make_error<AtomicFileWriteError>( + atomic_write_error::failed_to_create_uniq_file); + } + llvm::FileRemover RemoveTmpFileOnFail(GeneratedUniqPath); + + raw_fd_ostream OS(TempFD, /*shouldClose=*/true); + if (llvm::Error Err = Writer(OS)) { + return Err; + } + + OS.close(); + if (OS.has_error()) { + OS.clear_error(); + return llvm::make_error<AtomicFileWriteError>( + atomic_write_error::output_stream_error); + } + + if (const std::error_code Error = + sys::fs::rename(/*from=*/GeneratedUniqPath.c_str(), + /*to=*/FinalPath.str().c_str())) { + return llvm::make_error<AtomicFileWriteError>( + atomic_write_error::failed_to_rename_temp_file); + } + + RemoveTmpFileOnFail.releaseFile(); + return Error::success(); +} + +char llvm::AtomicFileWriteError::ID; |