| 375 | } |
| 376 | |
| 377 | static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> |
| 378 | getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize, |
| 379 | uint64_t Offset) { |
| 380 | Expected<sys::fs::file_t> FDOrErr = sys::fs::openNativeFileForReadWrite( |
| 381 | Filename, sys::fs::CD_OpenExisting, sys::fs::OF_None); |
| 382 | if (!FDOrErr) |
| 383 | return errorToErrorCode(FDOrErr.takeError()); |
| 384 | sys::fs::file_t FD = *FDOrErr; |
| 385 | |
| 386 | // Default is to map the full file. |
| 387 | if (MapSize == uint64_t(-1)) { |
| 388 | // If we don't know the file size, use fstat to find out. fstat on an open |
| 389 | // file descriptor is cheaper than stat on a random path. |
| 390 | if (FileSize == uint64_t(-1)) { |
| 391 | sys::fs::file_status Status; |
| 392 | std::error_code EC = sys::fs::status(FD, Status); |
| 393 | if (EC) |
| 394 | return EC; |
| 395 | |
| 396 | // If this not a file or a block device (e.g. it's a named pipe |
| 397 | // or character device), we can't mmap it, so error out. |
| 398 | sys::fs::file_type Type = Status.type(); |
| 399 | if (Type != sys::fs::file_type::regular_file && |
| 400 | Type != sys::fs::file_type::block_file) |
| 401 | return make_error_code(errc::invalid_argument); |
| 402 | |
| 403 | FileSize = Status.getSize(); |
| 404 | } |
| 405 | MapSize = FileSize; |
| 406 | } |
| 407 | |
| 408 | std::error_code EC; |
| 409 | std::unique_ptr<WriteThroughMemoryBuffer> Result( |
| 410 | new (NamedBufferAlloc(Filename)) |
| 411 | MemoryBufferMMapFile<WriteThroughMemoryBuffer>(false, FD, MapSize, |
| 412 | Offset, EC)); |
| 413 | if (EC) |
| 414 | return EC; |
| 415 | return std::move(Result); |
| 416 | } |
| 417 | |
| 418 | ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> |
| 419 | WriteThroughMemoryBuffer::getFile(const Twine &Filename, int64_t FileSize) { |
no test coverage detected