| 429 | |
| 430 | template <typename MB> |
| 431 | static ErrorOr<std::unique_ptr<MB>> |
| 432 | getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, |
| 433 | uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, |
| 434 | bool IsVolatile) { |
| 435 | static int PageSize = sys::Process::getPageSizeEstimate(); |
| 436 | |
| 437 | // Default is to map the full file. |
| 438 | if (MapSize == uint64_t(-1)) { |
| 439 | // If we don't know the file size, use fstat to find out. fstat on an open |
| 440 | // file descriptor is cheaper than stat on a random path. |
| 441 | if (FileSize == uint64_t(-1)) { |
| 442 | sys::fs::file_status Status; |
| 443 | std::error_code EC = sys::fs::status(FD, Status); |
| 444 | if (EC) |
| 445 | return EC; |
| 446 | |
| 447 | // If this not a file or a block device (e.g. it's a named pipe |
| 448 | // or character device), we can't trust the size. Create the memory |
| 449 | // buffer by copying off the stream. |
| 450 | sys::fs::file_type Type = Status.type(); |
| 451 | if (Type != sys::fs::file_type::regular_file && |
| 452 | Type != sys::fs::file_type::block_file) |
| 453 | return getMemoryBufferForStream(FD, Filename); |
| 454 | |
| 455 | FileSize = Status.getSize(); |
| 456 | } |
| 457 | MapSize = FileSize; |
| 458 | } |
| 459 | |
| 460 | if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator, |
| 461 | PageSize, IsVolatile)) { |
| 462 | std::error_code EC; |
| 463 | std::unique_ptr<MB> Result( |
| 464 | new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile<MB>( |
| 465 | RequiresNullTerminator, FD, MapSize, Offset, EC)); |
| 466 | if (!EC) |
| 467 | return std::move(Result); |
| 468 | } |
| 469 | |
| 470 | auto Buf = WritableMemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); |
| 471 | if (!Buf) { |
| 472 | // Failed to create a buffer. The only way it can fail is if |
| 473 | // new(std::nothrow) returns 0. |
| 474 | return make_error_code(errc::not_enough_memory); |
| 475 | } |
| 476 | |
| 477 | // Read until EOF, zero-initialize the rest. |
| 478 | MutableArrayRef<char> ToRead = Buf->getBuffer(); |
| 479 | while (!ToRead.empty()) { |
| 480 | Expected<size_t> ReadBytes = |
| 481 | sys::fs::readNativeFileSlice(FD, ToRead, Offset); |
| 482 | if (!ReadBytes) |
| 483 | return errorToErrorCode(ReadBytes.takeError()); |
| 484 | if (*ReadBytes == 0) { |
| 485 | std::memset(ToRead.data(), 0, ToRead.size()); |
| 486 | break; |
| 487 | } |
| 488 | ToRead = ToRead.drop_front(*ReadBytes); |
nothing calls this directly
no test coverage detected