-
-
- // If the file is large, try to use mmap to read it in. We don't use mmap
- // for small files, because this can severely fragment our address space. Also
- // don't try to map files that are exactly a multiple of the system page size,
- // as the file would not have the required null terminator.
- //
- // FIXME: Can we just mmap an extra page in the latter case?
- if (FileSize >= 4096*4 &&
- (FileSize & (sys::Process::GetPageSize()-1)) != 0) {
- if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) {
- // Close the file descriptor, now that the whole file is in memory.
- return new MemoryBufferMMapFile(Filename, Pages, FileSize);
+
+ // If we need a null terminator and the end of the map is inside the file,
+ // we cannot use mmap.
+ size_t End = Offset + MapSize;
+ assert(End <= FileSize);
+ if (End != FileSize)
+ return false;
+
+ // Don't try to map files that are exactly a multiple of the system page size
+ // if we need a null terminator.
+ if ((FileSize & (PageSize -1)) == 0)
+ return false;
+
+#if defined(__CYGWIN__)
+ // Don't try to map files that are exactly a multiple of the physical page size
+ // if we need a null terminator.
+ // FIXME: We should reorganize again getPageSize() on Win32.
+ if ((FileSize & (4096 - 1)) == 0)
+ return false;
+#endif
+
+ return true;
+}
+
+static ErrorOr<std::unique_ptr<MemoryBuffer>>
+getOpenFileImpl(int FD, const char *Filename, uint64_t FileSize,
+ uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
+ bool IsVolatileSize) {
+ static int PageSize = sys::process::get_self()->page_size();
+
+ // Default is to map the full file.
+ if (MapSize == uint64_t(-1)) {
+ // If we don't know the file size, use fstat to find out. fstat on an open
+ // file descriptor is cheaper than stat on a random path.
+ if (FileSize == uint64_t(-1)) {
+ sys::fs::file_status Status;
+ std::error_code EC = sys::fs::status(FD, Status);
+ if (EC)
+ return EC;
+
+ // If this not a file or a block device (e.g. it's a named pipe
+ // or character device), we can't trust the size. Create the memory
+ // buffer by copying off the stream.
+ sys::fs::file_type Type = Status.type();
+ if (Type != sys::fs::file_type::regular_file &&
+ Type != sys::fs::file_type::block_file)
+ return getMemoryBufferForStream(FD, Filename);
+
+ FileSize = Status.getSize();