FileOutputBuffer.cpp [plain text]
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Signals.h"
#include <system_error>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#else
#include <io.h>
#endif
using llvm::sys::fs::mapped_file_region;
namespace llvm {
FileOutputBuffer::FileOutputBuffer(std::unique_ptr<mapped_file_region> R,
StringRef Path, StringRef TmpPath)
: Region(std::move(R)), FinalPath(Path), TempPath(TmpPath) {}
FileOutputBuffer::~FileOutputBuffer() {
sys::fs::remove(Twine(TempPath));
}
ErrorOr<std::unique_ptr<FileOutputBuffer>>
FileOutputBuffer::create(StringRef FilePath, size_t Size, unsigned Flags) {
sys::fs::file_status Stat;
std::error_code EC = sys::fs::status(FilePath, Stat);
switch (Stat.type()) {
case sys::fs::file_type::file_not_found:
break;
case sys::fs::file_type::regular_file: {
}
break;
default:
if (EC)
return EC;
else
return make_error_code(errc::operation_not_permitted);
}
EC = sys::fs::remove(FilePath);
if (EC)
return EC;
unsigned Mode = sys::fs::all_read | sys::fs::all_write;
if (Flags & F_executable)
Mode |= sys::fs::all_exe;
SmallString<128> TempFilePath;
int FD;
EC = sys::fs::createUniqueFile(Twine(FilePath) + ".tmp%%%%%%%", FD,
TempFilePath, Mode);
if (EC)
return EC;
sys::RemoveFileOnSignal(TempFilePath);
#ifndef LLVM_ON_WIN32
EC = sys::fs::resize_file(FD, Size);
if (EC)
return EC;
#endif
auto MappedFile = llvm::make_unique<mapped_file_region>(
FD, mapped_file_region::readwrite, Size, 0, EC);
int Ret = close(FD);
if (EC)
return EC;
if (Ret)
return std::error_code(errno, std::generic_category());
std::unique_ptr<FileOutputBuffer> Buf(
new FileOutputBuffer(std::move(MappedFile), FilePath, TempFilePath));
return std::move(Buf);
}
std::error_code FileOutputBuffer::commit() {
Region.reset();
std::error_code EC = sys::fs::rename(Twine(TempPath), Twine(FinalPath));
sys::DontRemoveFileOnSignal(TempPath);
return EC;
}
}