LLVM  4.0.0
FileOutputBuffer.cpp
Go to the documentation of this file.
1 //===- FileOutputBuffer.cpp - File Output Buffer ----------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Utility for creating a in-memory buffer that will be written to a file.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/Support/Errc.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/Signals.h"
20 #include <system_error>
21 
22 #if !defined(_MSC_VER) && !defined(__MINGW32__)
23 #include <unistd.h>
24 #else
25 #include <io.h>
26 #endif
27 
29 
30 namespace llvm {
31 FileOutputBuffer::FileOutputBuffer(std::unique_ptr<mapped_file_region> R,
32  StringRef Path, StringRef TmpPath,
33  bool IsRegular)
34  : Region(std::move(R)), FinalPath(Path), TempPath(TmpPath),
35  IsRegular(IsRegular) {}
36 
38  // Close the mapping before deleting the temp file, so that the removal
39  // succeeds.
40  Region.reset();
41  sys::fs::remove(Twine(TempPath));
42 }
43 
45 FileOutputBuffer::create(StringRef FilePath, size_t Size, unsigned Flags) {
46  // Check file is not a regular file, in which case we cannot remove it.
48  std::error_code EC = sys::fs::status(FilePath, Stat);
49  bool IsRegular = true;
50  switch (Stat.type()) {
52  // If file does not exist, we'll create one.
53  break;
55  // If file is not currently writable, error out.
56  // FIXME: There is no sys::fs:: api for checking this.
57  // FIXME: In posix, you use the access() call to check this.
58  }
59  break;
60  default:
61  if (EC)
62  return EC;
63  IsRegular = false;
64  }
65 
66  if (IsRegular) {
67  // Delete target file.
68  EC = sys::fs::remove(FilePath);
69  if (EC)
70  return EC;
71  }
72 
73  SmallString<128> TempFilePath;
74  int FD;
75  if (IsRegular) {
77  // If requested, make the output file executable.
78  if (Flags & F_executable)
79  Mode |= sys::fs::all_exe;
80  // Create new file in same directory but with random name.
81  EC = sys::fs::createUniqueFile(Twine(FilePath) + ".tmp%%%%%%%", FD,
82  TempFilePath, Mode);
83  } else {
84  // Create a temporary file. Since this is a special file, we will not move
85  // it and the new file can be in another filesystem. This avoids trying to
86  // create a temporary file in /dev when outputting to /dev/null for example.
88  TempFilePath);
89  }
90 
91  if (EC)
92  return EC;
93 
94  sys::RemoveFileOnSignal(TempFilePath);
95 
96 #ifndef LLVM_ON_WIN32
97  // On Windows, CreateFileMapping (the mmap function on Windows)
98  // automatically extends the underlying file. We don't need to
99  // extend the file beforehand. _chsize (ftruncate on Windows) is
100  // pretty slow just like it writes specified amount of bytes,
101  // so we should avoid calling that.
102  EC = sys::fs::resize_file(FD, Size);
103  if (EC)
104  return EC;
105 #endif
106 
107  auto MappedFile = llvm::make_unique<mapped_file_region>(
108  FD, mapped_file_region::readwrite, Size, 0, EC);
109  int Ret = close(FD);
110  if (EC)
111  return EC;
112  if (Ret)
113  return std::error_code(errno, std::generic_category());
114 
115  std::unique_ptr<FileOutputBuffer> Buf(new FileOutputBuffer(
116  std::move(MappedFile), FilePath, TempFilePath, IsRegular));
117  return std::move(Buf);
118 }
119 
120 std::error_code FileOutputBuffer::commit() {
121  // Unmap buffer, letting OS flush dirty pages to file on disk.
122  Region.reset();
123 
124  std::error_code EC;
125  if (IsRegular) {
126  // Rename file to final name.
127  EC = sys::fs::rename(Twine(TempPath), Twine(FinalPath));
128  sys::DontRemoveFileOnSignal(TempPath);
129  } else {
130  EC = sys::fs::copy_file(TempPath, FinalPath);
131  std::error_code RMEC = sys::fs::remove(TempPath);
132  sys::DontRemoveFileOnSignal(TempPath);
133  if (RMEC)
134  return RMEC;
135  }
136 
137  return EC;
138 }
139 } // namespace
Represents either an error or a value T.
Definition: ErrorOr.h:68
SI Whole Quad Mode
std::error_code createUniqueFile(const Twine &Model, int &ResultFD, SmallVectorImpl< char > &ResultPath, unsigned Mode=all_read|all_write)
Create a uniquely named file.
Definition: Path.cpp:762
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
This class represents a memory mapped file.
Definition: FileSystem.h:685
file_status - Represents the result of a call to stat and friends.
Definition: FileSystem.h:142
~FileOutputBuffer()
If this object was previously committed, the destructor just deletes this object. ...
struct fuzzer::@269 Flags
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
FileOutputBuffer - This interface provides simple way to create an in-memory buffer which will be wri...
std::error_code commit()
Flushes the content of the buffer to its file and deallocates the buffer.
std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition: Path.cpp:906
StringRef filename(StringRef path)
Get filename.
Definition: Path.cpp:584
std::error_code resize_file(int FD, uint64_t Size)
Resize path to size.
void DontRemoveFileOnSignal(StringRef Filename)
This function removes a file from the list of files to be removed on signal delivery.
static ErrorOr< std::unique_ptr< FileOutputBuffer > > create(StringRef FilePath, size_t Size, unsigned Flags=0)
Factory method to create an OutputBuffer object which manages a read/write buffer of the specified si...
std::error_code rename(const Twine &from, const Twine &to)
Rename from to to.
bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg=nullptr)
This function registers signal handlers to ensure that if a signal gets delivered that the named file...
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath)
Create a file in the system temporary directory.
Definition: Path.cpp:794
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
std::error_code status(const Twine &path, file_status &result)
Get file status as if by POSIX stat().
file_type type() const
Definition: FileSystem.h:211