diff options
Diffstat (limited to 'contrib/llvm/lib/Support/FileOutputBuffer.cpp')
-rw-r--r-- | contrib/llvm/lib/Support/FileOutputBuffer.cpp | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/contrib/llvm/lib/Support/FileOutputBuffer.cpp b/contrib/llvm/lib/Support/FileOutputBuffer.cpp index c4ff563e5f44..1214b5a0ba1f 100644 --- a/contrib/llvm/lib/Support/FileOutputBuffer.cpp +++ b/contrib/llvm/lib/Support/FileOutputBuffer.cpp @@ -82,9 +82,11 @@ public: size_t getBufferSize() const override { return Buffer.size(); } Error commit() override { + using namespace sys::fs; int FD; std::error_code EC; - if (auto EC = openFileForWrite(FinalPath, FD, fs::F_None, Mode)) + if (auto EC = + openFileForWrite(FinalPath, FD, CD_CreateAlways, OF_None, Mode)) return errorCodeToError(EC); raw_fd_ostream OS(FD, /*shouldClose=*/true, /*unbuffered=*/true); OS << StringRef((const char *)Buffer.base(), Buffer.size()); @@ -108,24 +110,30 @@ createInMemoryBuffer(StringRef Path, size_t Size, unsigned Mode) { } static Expected<std::unique_ptr<OnDiskBuffer>> -createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode) { +createOnDiskBuffer(StringRef Path, size_t Size, bool InitExisting, + unsigned Mode) { Expected<fs::TempFile> FileOrErr = fs::TempFile::create(Path + ".tmp%%%%%%%", Mode); if (!FileOrErr) return FileOrErr.takeError(); fs::TempFile File = std::move(*FileOrErr); -#ifndef LLVM_ON_WIN32 - // On Windows, CreateFileMapping (the mmap function on Windows) - // automatically extends the underlying file. We don't need to - // extend the file beforehand. _chsize (ftruncate on Windows) is - // pretty slow just like it writes specified amount of bytes, - // so we should avoid calling that function. - if (auto EC = fs::resize_file(File.FD, Size)) { - consumeError(File.discard()); - return errorCodeToError(EC); - } + if (InitExisting) { + if (auto EC = sys::fs::copy_file(Path, File.FD)) + return errorCodeToError(EC); + } else { +#ifndef _WIN32 + // On Windows, CreateFileMapping (the mmap function on Windows) + // automatically extends the underlying file. We don't need to + // extend the file beforehand. _chsize (ftruncate on Windows) is + // pretty slow just like it writes specified amount of bytes, + // so we should avoid calling that function. + if (auto EC = fs::resize_file(File.FD, Size)) { + consumeError(File.discard()); + return errorCodeToError(EC); + } #endif + } // Mmap it. std::error_code EC; @@ -149,6 +157,15 @@ FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags) { fs::file_status Stat; fs::status(Path, Stat); + if ((Flags & F_modify) && Size == size_t(-1)) { + if (Stat.type() == fs::file_type::regular_file) + Size = Stat.getSize(); + else if (Stat.type() == fs::file_type::file_not_found) + return errorCodeToError(errc::no_such_file_or_directory); + else + return errorCodeToError(errc::invalid_argument); + } + // Usually, we want to create OnDiskBuffer to create a temporary file in // the same directory as the destination file and atomically replaces it // by rename(2). @@ -163,7 +180,7 @@ FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags) { case fs::file_type::regular_file: case fs::file_type::file_not_found: case fs::file_type::status_error: - return createOnDiskBuffer(Path, Size, Mode); + return createOnDiskBuffer(Path, Size, !!(Flags & F_modify), Mode); default: return createInMemoryBuffer(Path, Size, Mode); } |