Update the non-pthreads fallback for RWMutex on Unix
[oota-llvm.git] / lib / Support / FileOutputBuffer.cpp
index 7dc9587caae29529bcc0bf6d7f7fd4dfd5e37354..c62655d58d5fa16f564c710008eb4b1dc3bb3b90 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/FileOutputBuffer.h"
-
-#include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/FileSystem.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/system_error.h"
+#include <system_error>
 
+using llvm::sys::fs::mapped_file_region;
 
 namespace llvm {
-
-
-FileOutputBuffer::FileOutputBuffer(uint8_t *Start, uint8_t *End, 
-                                  StringRef Path, StringRef TmpPath)
-  : BufferStart(Start), BufferEnd(End) {
-  FinalPath.assign(Path);
-  TempPath.assign(TmpPath);
-}
-
+FileOutputBuffer::FileOutputBuffer(std::unique_ptr<mapped_file_region> R,
+                                   StringRef Path, StringRef TmpPath)
+    : Region(std::move(R)), FinalPath(Path), TempPath(TmpPath) {}
 
 FileOutputBuffer::~FileOutputBuffer() {
-  // If not already commited, delete buffer and remove temp file.
-  if ( BufferStart != NULL ) {
-    sys::fs::unmap_file_pages((void*)BufferStart, getBufferSize());
-    bool Existed;
-    sys::fs::remove(Twine(TempPath), Existed);
-  }
+  sys::fs::remove(Twine(TempPath));
 }
 
-error_code FileOutputBuffer::create(StringRef FilePath, 
-                                    size_t Size,  
-                                    OwningPtr<FileOutputBuffer> &Result,
-                                    unsigned Flags) {
+std::error_code
+FileOutputBuffer::create(StringRef FilePath, size_t Size,
+                         std::unique_ptr<FileOutputBuffer> &Result,
+                         unsigned Flags) {
   // If file already exists, it must be a regular file (to be mappable).
   sys::fs::file_status Stat;
-  error_code EC = sys::fs::status(FilePath, Stat);
+  std::error_code EC = sys::fs::status(FilePath, Stat);
   switch (Stat.type()) {
     case sys::fs::file_type::file_not_found:
       // If file does not exist, we'll create one.
@@ -66,83 +54,46 @@ error_code FileOutputBuffer::create(StringRef FilePath,
   }
 
   // Delete target file.
-  bool Existed;
-  EC = sys::fs::remove(FilePath, Existed);
+  EC = sys::fs::remove(FilePath);
   if (EC)
     return EC;
-  
+
+  unsigned Mode = sys::fs::all_read | sys::fs::all_write;
+  // If requested, make the output file executable.
+  if (Flags & F_executable)
+    Mode |= sys::fs::all_exe;
+
   // Create new file in same directory but with random name.
   SmallString<128> TempFilePath;
   int FD;
-  EC = sys::fs::unique_file(Twine(FilePath) + ".tmp%%%%%%%",  
-                                                FD, TempFilePath, false, 0644);
+  EC = sys::fs::createUniqueFile(Twine(FilePath) + ".tmp%%%%%%%", FD,
+                                 TempFilePath, Mode);
   if (EC)
     return EC;
-  
-  // The unique_file() interface leaks lower layers and returns a file 
-  // descriptor.  There is no way to directly close it, so use this hack
-  // to hand it off to raw_fd_ostream to close for us.
-  {
-    raw_fd_ostream Dummy(FD, /*shouldClose=*/true);
-  }
-  
-  // Resize file to requested initial size
-  EC = sys::fs::resize_file(Twine(TempFilePath), Size);
-  if (EC)
-    return EC;
-  
-  // If requested, make the output file executable.
-  if ( Flags & F_executable ) {
-    sys::fs::file_status Stat2;
-    EC = sys::fs::status(Twine(TempFilePath), Stat2);
-    if (EC)
-      return EC;
-    
-    sys::fs::perms new_perms = Stat2.permissions();
-    if ( new_perms & sys::fs::owner_read )
-      new_perms |= sys::fs::owner_exe;
-    if ( new_perms & sys::fs::group_read )
-      new_perms |= sys::fs::group_exe;
-    if ( new_perms & sys::fs::others_read )
-      new_perms |= sys::fs::others_exe;
-    new_perms |= sys::fs::add_perms;
-    EC = sys::fs::permissions(Twine(TempFilePath), new_perms);
-    if (EC)
-      return EC;
-  }
 
-  // Memory map new file.
-  void *Base;
-  EC = sys::fs::map_file_pages(Twine(TempFilePath), 0, Size, true, Base);
+  auto MappedFile = llvm::make_unique<mapped_file_region>(
+      FD, true, mapped_file_region::readwrite, Size, 0, EC);
   if (EC)
     return EC;
-  
-  // Create FileOutputBuffer object to own mapped range.
-  uint8_t *Start = reinterpret_cast<uint8_t*>(Base);
-  Result.reset(new FileOutputBuffer(Start, Start+Size, FilePath, TempFilePath));
-                     
-  return error_code::success();
-}                    
 
+  Result.reset(
+      new FileOutputBuffer(std::move(MappedFile), FilePath, TempFilePath));
 
-error_code FileOutputBuffer::commit(int64_t NewSmallerSize) {
+  return std::error_code();
+}
+
+std::error_code FileOutputBuffer::commit(int64_t NewSmallerSize) {
   // Unmap buffer, letting OS flush dirty pages to file on disk.
-  void *Start = reinterpret_cast<void*>(BufferStart);
-  error_code EC = sys::fs::unmap_file_pages(Start, getBufferSize());
-  if (EC)
-    return EC;
-  
+  Region.reset();
+
   // If requested, resize file as part of commit.
   if ( NewSmallerSize != -1 ) {
-    EC = sys::fs::resize_file(Twine(TempPath), NewSmallerSize);
+    std::error_code EC = sys::fs::resize_file(Twine(TempPath), NewSmallerSize);
     if (EC)
       return EC;
   }
-  
+
   // Rename file to final name.
   return sys::fs::rename(Twine(TempPath), Twine(FinalPath));
 }
-
-
 } // namespace
-