Index: clang/lib/IndexSerialization/FSUtil.h =================================================================== --- /dev/null +++ clang/lib/IndexSerialization/FSUtil.h @@ -0,0 +1,67 @@ +//===--- FSUtil.h - File system utilities ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_FSUTIL_H +#define LLVM_CLANG_INDEX_FSUTIL_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { +namespace index { + +using namespace llvm; + +/// Creates a unique file with name according to the given \p TempPathModel, +/// writes content of \p Buffer to the file and renames it to \p FinalPath. +/// \returns false when the file was successfully created, true otherwise. +inline bool atomicFileWrite(StringRef TempPathModel, StringRef FinalPath, + const SmallString<512> &Buffer, + std::string &Error) { + SmallString<128> GeneratedUniqPath; + int TempFD; + if (sys::fs::createUniqueFile(TempPathModel.str(), TempFD, + GeneratedUniqPath)) { + raw_string_ostream Err(Error); + Err << "failed to create temporary file: " << TempPathModel; + return true; + } + + raw_fd_ostream OS(TempFD, /*shouldClose=*/true); + OS.write(Buffer.data(), Buffer.size()); + OS.close(); + TempFD = -1; + + if (OS.has_error()) { + raw_string_ostream Err(Error); + Err << "failed to write '" << GeneratedUniqPath + << "': " << OS.error().message(); + OS.clear_error(); + return true; + } + + std::error_code EC = sys::fs::rename(/*from=*/GeneratedUniqPath.c_str(), + /*to=*/FinalPath.str().c_str()); + if (EC) { + raw_string_ostream Err(Error); + Err << "failed to rename '" << GeneratedUniqPath << "' to '" << FinalPath + << "': " << EC.message(); + return true; + } + + return false; +} + +} // end namespace index +} // end namespace clang + +#endif