diff options
Diffstat (limited to 'lib/Support/FileOutputBuffer.cpp')
| -rw-r--r-- | lib/Support/FileOutputBuffer.cpp | 43 | 
1 files changed, 30 insertions, 13 deletions
| diff --git a/lib/Support/FileOutputBuffer.cpp b/lib/Support/FileOutputBuffer.cpp index c4ff563e5f44..1214b5a0ba1f 100644 --- a/lib/Support/FileOutputBuffer.cpp +++ b/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);    } | 
