FileOutputBuffer.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
1727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease//===- FileOutputBuffer.cpp - File Output Buffer ----------------*- C++ -*-===// 2727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease// 3727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease// The LLVM Compiler Infrastructure 4727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease// 5727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease// This file is distributed under the University of Illinois Open Source 6727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease// License. See LICENSE.TXT for details. 7727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease// 8727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease//===----------------------------------------------------------------------===// 9727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease// 10727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease// Utility for creating a in-memory buffer that will be written to a file. 11727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease// 12727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease//===----------------------------------------------------------------------===// 13727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 14727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include "llvm/Support/Errc.h" 15727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include "llvm/Support/FileOutputBuffer.h" 16727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include "llvm/ADT/SmallVector.h" 17727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include "llvm/Support/raw_ostream.h" 18727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include <system_error> 19727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 20727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Leaseusing llvm::sys::fs::mapped_file_region; 21727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 22727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Leasenamespace llvm { 23727dee178a392d20eb050d0c446f2fcc29058fa1Victoria LeaseFileOutputBuffer::FileOutputBuffer(mapped_file_region * R, 24727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease StringRef Path, StringRef TmpPath) 25727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease : Region(R) 26727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease , FinalPath(Path) 27727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease , TempPath(TmpPath) { 28727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease} 29727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 30727dee178a392d20eb050d0c446f2fcc29058fa1Victoria LeaseFileOutputBuffer::~FileOutputBuffer() { 31727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease sys::fs::remove(Twine(TempPath)); 32727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease} 33727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 34727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Leasestd::error_code 35727dee178a392d20eb050d0c446f2fcc29058fa1Victoria LeaseFileOutputBuffer::create(StringRef FilePath, size_t Size, 36727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease std::unique_ptr<FileOutputBuffer> &Result, 37727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease unsigned Flags) { 38727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // If file already exists, it must be a regular file (to be mappable). 39727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease sys::fs::file_status Stat; 40727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease std::error_code EC = sys::fs::status(FilePath, Stat); 41727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease switch (Stat.type()) { 42727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease case sys::fs::file_type::file_not_found: 43727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // If file does not exist, we'll create one. 44727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease break; 45727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease case sys::fs::file_type::regular_file: { 46727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // If file is not currently writable, error out. 47727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // FIXME: There is no sys::fs:: api for checking this. 48727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // FIXME: In posix, you use the access() call to check this. 49727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease } 50727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease break; 51727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease default: 52727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease if (EC) 53727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return EC; 54727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease else 55727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return make_error_code(errc::operation_not_permitted); 56727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease } 57727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 58727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // Delete target file. 59727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease EC = sys::fs::remove(FilePath); 60727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease if (EC) 61727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return EC; 62727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 63727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease unsigned Mode = sys::fs::all_read | sys::fs::all_write; 64727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // If requested, make the output file executable. 65727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease if (Flags & F_executable) 66727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease Mode |= sys::fs::all_exe; 67727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 68727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // Create new file in same directory but with random name. 69727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease SmallString<128> TempFilePath; 70727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease int FD; 71727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease EC = sys::fs::createUniqueFile(Twine(FilePath) + ".tmp%%%%%%%", FD, 72727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease TempFilePath, Mode); 73727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease if (EC) 74727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return EC; 75727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 76727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease std::unique_ptr<mapped_file_region> MappedFile(new mapped_file_region( 77727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease FD, true, mapped_file_region::readwrite, Size, 0, EC)); 78727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease if (EC) 79727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return EC; 80727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 81727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease Result.reset(new FileOutputBuffer(MappedFile.get(), FilePath, TempFilePath)); 82727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease if (Result) 83727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease MappedFile.release(); 84727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 85727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return std::error_code(); 86727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease} 87727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 88727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Leasestd::error_code FileOutputBuffer::commit(int64_t NewSmallerSize) { 89727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // Unmap buffer, letting OS flush dirty pages to file on disk. 90727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease Region.reset(nullptr); 91727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 92727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // If requested, resize file as part of commit. 93727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease if ( NewSmallerSize != -1 ) { 94727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease std::error_code EC = sys::fs::resize_file(Twine(TempPath), NewSmallerSize); 95727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease if (EC) 96727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return EC; 97727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease } 98727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 99727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease // Rename file to final name. 100727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return sys::fs::rename(Twine(TempPath), Twine(FinalPath)); 101727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease} 102727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease} // namespace 103727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease