diff options
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r-- | llvm/lib/Support/FileOutputBuffer.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Support/MemoryBuffer.cpp | 87 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Path.inc | 49 | ||||
-rw-r--r-- | llvm/lib/Support/VirtualFileSystem.cpp | 27 | ||||
-rw-r--r-- | llvm/lib/Support/Windows/Path.inc | 82 |
5 files changed, 170 insertions, 78 deletions
diff --git a/llvm/lib/Support/FileOutputBuffer.cpp b/llvm/lib/Support/FileOutputBuffer.cpp index 19ab2e9917a..3d6b569f299 100644 --- a/llvm/lib/Support/FileOutputBuffer.cpp +++ b/llvm/lib/Support/FileOutputBuffer.cpp @@ -147,7 +147,8 @@ createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode) { // Mmap it. std::error_code EC; auto MappedFile = llvm::make_unique<fs::mapped_file_region>( - File.FD, fs::mapped_file_region::readwrite, Size, 0, EC); + fs::convertFDToNativeFile(File.FD), fs::mapped_file_region::readwrite, + Size, 0, EC); // mmap(2) can fail if the underlying filesystem does not support it. // If that happens, we fall back to in-memory buffer as the last resort. diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp index 92e39e118b9..d0e5bb154c1 100644 --- a/llvm/lib/Support/MemoryBuffer.cpp +++ b/llvm/lib/Support/MemoryBuffer.cpp @@ -182,7 +182,7 @@ class MemoryBufferMMapFile : public MB { } public: - MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len, + MemoryBufferMMapFile(bool RequiresNullTerminator, sys::fs::file_t FD, uint64_t Len, uint64_t Offset, std::error_code &EC) : MFR(FD, MB::Mapmode, getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) { @@ -208,16 +208,16 @@ public: } static ErrorOr<std::unique_ptr<WritableMemoryBuffer>> -getMemoryBufferForStream(int FD, const Twine &BufferName) { +getMemoryBufferForStream(sys::fs::file_t FD, const Twine &BufferName) { const ssize_t ChunkSize = 4096*4; SmallString<ChunkSize> Buffer; - ssize_t ReadBytes; + size_t ReadBytes; // Read into Buffer until we hit EOF. do { Buffer.reserve(Buffer.size() + ChunkSize); - ReadBytes = sys::RetryAfterSignal(-1, ::read, FD, Buffer.end(), ChunkSize); - if (ReadBytes == -1) - return std::error_code(errno, std::generic_category()); + if (auto EC = sys::fs::readNativeFile( + FD, makeMutableArrayRef(Buffer.end(), ChunkSize), &ReadBytes)) + return EC; Buffer.set_size(Buffer.size() + ReadBytes); } while (ReadBytes != 0); @@ -234,7 +234,7 @@ MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize, template <typename MB> static ErrorOr<std::unique_ptr<MB>> -getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, +getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, bool IsVolatile); @@ -242,15 +242,14 @@ template <typename MB> static ErrorOr<std::unique_ptr<MB>> getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile) { - int FD; - std::error_code EC = sys::fs::openFileForRead(Filename, FD, sys::fs::OF_None); - - if (EC) - return EC; - + Expected<sys::fs::file_t> FDOrErr = + sys::fs::openNativeFileForRead(Filename, sys::fs::OF_None); + if (!FDOrErr) + return errorToErrorCode(FDOrErr.takeError()); + sys::fs::file_t FD = *FDOrErr; auto Ret = getOpenFileImpl<MB>(FD, Filename, FileSize, MapSize, Offset, RequiresNullTerminator, IsVolatile); - close(FD); + sys::fs::closeFile(FD); return Ret; } @@ -304,7 +303,7 @@ WritableMemoryBuffer::getNewMemBuffer(size_t Size, const Twine &BufferName) { return SB; } -static bool shouldUseMmap(int FD, +static bool shouldUseMmap(sys::fs::file_t FD, size_t FileSize, size_t MapSize, off_t Offset, @@ -362,12 +361,11 @@ static bool shouldUseMmap(int FD, static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize, uint64_t Offset) { - int FD; - std::error_code EC = sys::fs::openFileForReadWrite( - Filename, FD, sys::fs::CD_OpenExisting, sys::fs::OF_None); - - if (EC) - return EC; + Expected<sys::fs::file_t> FDOrErr = sys::fs::openNativeFileForReadWrite( + Filename, sys::fs::CD_OpenExisting, sys::fs::OF_None); + if (!FDOrErr) + return errorToErrorCode(FDOrErr.takeError()); + sys::fs::file_t FD = *FDOrErr; // Default is to map the full file. if (MapSize == uint64_t(-1)) { @@ -391,6 +389,7 @@ getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize, MapSize = FileSize; } + std::error_code EC; std::unique_ptr<WriteThroughMemoryBuffer> Result( new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile<WriteThroughMemoryBuffer>(false, FD, MapSize, @@ -414,7 +413,7 @@ WriteThroughMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize, template <typename MB> static ErrorOr<std::unique_ptr<MB>> -getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, +getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, bool IsVolatile) { static int PageSize = sys::Process::getPageSizeEstimate(); @@ -459,45 +458,20 @@ getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, return make_error_code(errc::not_enough_memory); } - char *BufPtr = Buf.get()->getBufferStart(); - - size_t BytesLeft = MapSize; -#ifndef HAVE_PREAD - if (lseek(FD, Offset, SEEK_SET) == -1) - return std::error_code(errno, std::generic_category()); -#endif - - while (BytesLeft) { -#ifdef HAVE_PREAD - ssize_t NumRead = sys::RetryAfterSignal(-1, ::pread, FD, BufPtr, BytesLeft, - MapSize - BytesLeft + Offset); -#else - ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, BufPtr, BytesLeft); -#endif - if (NumRead == -1) { - // Error while reading. - return std::error_code(errno, std::generic_category()); - } - if (NumRead == 0) { - memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer. - break; - } - BytesLeft -= NumRead; - BufPtr += NumRead; - } + sys::fs::readNativeFileSlice(FD, Buf->getBuffer(), Offset); return std::move(Buf); } ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, +MemoryBuffer::getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator, bool IsVolatile) { return getOpenFileImpl<MemoryBuffer>(FD, Filename, FileSize, FileSize, 0, RequiresNullTerminator, IsVolatile); } ErrorOr<std::unique_ptr<MemoryBuffer>> -MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, +MemoryBuffer::getOpenFileSlice(sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize, int64_t Offset, bool IsVolatile) { assert(MapSize != uint64_t(-1)); return getOpenFileImpl<MemoryBuffer>(FD, Filename, -1, MapSize, Offset, false, @@ -511,18 +485,19 @@ ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() { // fallback if it fails. sys::ChangeStdinToBinary(); - return getMemoryBufferForStream(0, "<stdin>"); + return getMemoryBufferForStream(sys::fs::getStdinHandle(), "<stdin>"); } ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getFileAsStream(const Twine &Filename) { - int FD; - std::error_code EC = sys::fs::openFileForRead(Filename, FD, sys::fs::OF_None); - if (EC) - return EC; + Expected<sys::fs::file_t> FDOrErr = + sys::fs::openNativeFileForRead(Filename, sys::fs::OF_None); + if (!FDOrErr) + return errorToErrorCode(FDOrErr.takeError()); + sys::fs::file_t FD = *FDOrErr; ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = getMemoryBufferForStream(FD, Filename); - close(FD); + sys::fs::closeFile(FD); return Ret; } diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc index c64c0df19ad..58c15023bab 100644 --- a/llvm/lib/Support/Unix/Path.inc +++ b/llvm/lib/Support/Unix/Path.inc @@ -990,9 +990,54 @@ Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags, return ResultFD; } -void closeFile(file_t &F) { - ::close(F); +file_t getStdinHandle() { return 0; } +file_t getStdoutHandle() { return 1; } +file_t getStderrHandle() { return 2; } + +std::error_code readNativeFile(file_t FD, MutableArrayRef<char> Buf, + size_t *BytesRead) { + *BytesRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Buf.size()); + if (ssize_t(*BytesRead) == -1) + return std::error_code(errno, std::generic_category()); + return std::error_code(); +} + +std::error_code readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf, + size_t Offset) { + char *BufPtr = Buf.data(); + size_t BytesLeft = Buf.size(); + +#ifndef HAVE_PREAD + // If we don't have pread, seek to Offset. + if (lseek(FD, Offset, SEEK_SET) == -1) + return std::error_code(errno, std::generic_category()); +#endif + + while (BytesLeft) { +#ifdef HAVE_PREAD + ssize_t NumRead = sys::RetryAfterSignal(-1, ::pread, FD, BufPtr, BytesLeft, + Buf.size() - BytesLeft + Offset); +#else + ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, BufPtr, BytesLeft); +#endif + if (NumRead == -1) { + // Error while reading. + return std::error_code(errno, std::generic_category()); + } + if (NumRead == 0) { + memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer. + break; + } + BytesLeft -= NumRead; + BufPtr += NumRead; + } + return std::error_code(); +} + +std::error_code closeFile(file_t &F) { + file_t TmpF = F; F = kInvalidFile; + return Process::SafelyCloseFileDescriptor(TmpF); } template <typename T> diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 48ce31491a8..5d3480e9714 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -56,8 +56,10 @@ using namespace llvm; using namespace llvm::vfs; +using llvm::sys::fs::file_t; using llvm::sys::fs::file_status; using llvm::sys::fs::file_type; +using llvm::sys::fs::kInvalidFile; using llvm::sys::fs::perms; using llvm::sys::fs::UniqueID; @@ -170,15 +172,15 @@ namespace { class RealFile : public File { friend class RealFileSystem; - int FD; + file_t FD; Status S; std::string RealName; - RealFile(int FD, StringRef NewName, StringRef NewRealPathName) + RealFile(file_t FD, StringRef NewName, StringRef NewRealPathName) : FD(FD), S(NewName, {}, {}, {}, {}, {}, llvm::sys::fs::file_type::status_error, {}), RealName(NewRealPathName.str()) { - assert(FD >= 0 && "Invalid or inactive file descriptor"); + assert(FD != kInvalidFile && "Invalid or inactive file descriptor"); } public: @@ -198,7 +200,7 @@ public: RealFile::~RealFile() { close(); } ErrorOr<Status> RealFile::status() { - assert(FD != -1 && "cannot stat closed file"); + assert(FD != kInvalidFile && "cannot stat closed file"); if (!S.isStatusKnown()) { file_status RealStatus; if (std::error_code EC = sys::fs::status(FD, RealStatus)) @@ -215,14 +217,14 @@ ErrorOr<std::string> RealFile::getName() { ErrorOr<std::unique_ptr<MemoryBuffer>> RealFile::getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, bool IsVolatile) { - assert(FD != -1 && "cannot get buffer for closed file"); + assert(FD != kInvalidFile && "cannot get buffer for closed file"); return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator, IsVolatile); } std::error_code RealFile::close() { - std::error_code EC = sys::Process::SafelyCloseFileDescriptor(FD); - FD = -1; + std::error_code EC = sys::fs::closeFile(FD); + FD = kInvalidFile; return EC; } @@ -293,12 +295,13 @@ ErrorOr<Status> RealFileSystem::status(const Twine &Path) { ErrorOr<std::unique_ptr<File>> RealFileSystem::openFileForRead(const Twine &Name) { - int FD; SmallString<256> RealName, Storage; - if (std::error_code EC = sys::fs::openFileForRead( - adjustPath(Name, Storage), FD, sys::fs::OF_None, &RealName)) - return EC; - return std::unique_ptr<File>(new RealFile(FD, Name.str(), RealName.str())); + Expected<file_t> FDOrErr = sys::fs::openNativeFileForRead( + adjustPath(Name, Storage), sys::fs::OF_None, &RealName); + if (!FDOrErr) + return errorToErrorCode(FDOrErr.takeError()); + return std::unique_ptr<File>( + new RealFile(*FDOrErr, Name.str(), RealName.str())); } llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const { diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc index 9adda233c02..045d0b9ed58 100644 --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -734,6 +734,10 @@ std::error_code status(int FD, file_status &Result) { return getStatus(FileHandle, Result); } +std::error_code status(file_t FileHandle, file_status &Result) { + return getStatus(FileHandle, Result); +} + unsigned getUmask() { return 0; } @@ -780,10 +784,9 @@ std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, return std::error_code(); } -std::error_code mapped_file_region::init(int FD, uint64_t Offset, - mapmode Mode) { +std::error_code mapped_file_region::init(sys::fs::file_t OrigFileHandle, + uint64_t Offset, mapmode Mode) { this->Mode = Mode; - HANDLE OrigFileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); if (OrigFileHandle == INVALID_HANDLE_VALUE) return make_error_code(errc::bad_file_descriptor); @@ -850,8 +853,9 @@ std::error_code mapped_file_region::init(int FD, uint64_t Offset, return std::error_code(); } -mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length, - uint64_t offset, std::error_code &ec) +mapped_file_region::mapped_file_region(sys::fs::file_t fd, mapmode mode, + size_t length, uint64_t offset, + std::error_code &ec) : Size(length), Mapping() { ec = init(fd, offset, mode); if (ec) @@ -1201,9 +1205,73 @@ Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags, return Result; } -void closeFile(file_t &F) { - ::CloseHandle(F); +file_t convertFDToNativeFile(int FD) { + return reinterpret_cast<HANDLE>(::_get_osfhandle(FD)); +} + +file_t getStdinHandle() { return ::GetStdHandle(STD_INPUT_HANDLE); } +file_t getStdoutHandle() { return ::GetStdHandle(STD_OUTPUT_HANDLE); } +file_t getStderrHandle() { return ::GetStdHandle(STD_ERROR_HANDLE); } + +std::error_code readNativeFileImpl(file_t FileHandle, char *BufPtr, size_t BytesToRead, + size_t *BytesRead, OVERLAPPED *Overlap) { + // ReadFile can only read 2GB at a time. The caller should check the number of + // bytes and read in a loop until termination. + DWORD BytesToRead32 = + std::min(size_t(std::numeric_limits<DWORD>::max()), BytesToRead); + DWORD BytesRead32 = 0; + bool Success = + ::ReadFile(FileHandle, BufPtr, BytesToRead32, &BytesRead32, Overlap); + *BytesRead = BytesRead32; + if (!Success) { + DWORD Err = ::GetLastError(); + // Pipe EOF is not an error. + if (Err == ERROR_BROKEN_PIPE) + return std::error_code(); + return mapWindowsError(Err); + } + return std::error_code(); +} + +std::error_code readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf, + size_t *BytesRead) { + return readNativeFileImpl(FileHandle, Buf.data(), Buf.size(), BytesRead, + /*Overlap=*/nullptr); +} + +std::error_code readNativeFileSlice(file_t FileHandle, + MutableArrayRef<char> Buf, size_t Offset) { + char *BufPtr = Buf.data(); + size_t BytesLeft = Buf.size(); + + while (BytesLeft) { + uint64_t CurOff = Buf.size() - BytesLeft + Offset; + OVERLAPPED Overlapped = {}; + Overlapped.Offset = uint32_t(CurOff); + Overlapped.OffsetHigh = uint32_t(uint64_t(CurOff) >> 32); + + size_t BytesRead = 0; + if (auto EC = readNativeFileImpl(FileHandle, BufPtr, BytesLeft, &BytesRead, + &Overlapped)) + return EC; + + // Once we reach EOF, zero the remaining bytes in the buffer. + if (BytesRead == 0) { + memset(BufPtr, 0, BytesLeft); + break; + } + BytesLeft -= BytesRead; + BufPtr += BytesRead; + } + return std::error_code(); +} + +std::error_code closeFile(file_t &F) { + file_t TmpF = F; F = kInvalidFile; + if (!::CloseHandle(TmpF)) + return mapWindowsError(::GetLastError()); + return std::error_code(); } std::error_code remove_directories(const Twine &path, bool IgnoreErrors) { |