//
//===----------------------------------------------------------------------===//
+#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.
}
// 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
-