1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/files/memory_mapped_file.h" 6 7 #include <sys/mman.h> 8 #include <sys/stat.h> 9 #include <unistd.h> 10 11 #include "base/logging.h" 12 #include "base/threading/thread_restrictions.h" 13 14 namespace base { 15 16 MemoryMappedFile::MemoryMappedFile() : data_(NULL), length_(0) { 17 } 18 19 bool MemoryMappedFile::MapFileRegionToMemory( 20 const MemoryMappedFile::Region& region) { 21 ThreadRestrictions::AssertIOAllowed(); 22 23 off_t map_start = 0; 24 size_t map_size = 0; 25 int32 data_offset = 0; 26 27 if (region == MemoryMappedFile::Region::kWholeFile) { 28 int64 file_len = file_.GetLength(); 29 if (file_len == -1) { 30 DPLOG(ERROR) << "fstat " << file_.GetPlatformFile(); 31 return false; 32 } 33 map_size = static_cast<size_t>(file_len); 34 length_ = map_size; 35 } else { 36 // The region can be arbitrarily aligned. mmap, instead, requires both the 37 // start and size to be page-aligned. Hence, we map here the page-aligned 38 // outer region [|aligned_start|, |aligned_start| + |size|] which contains 39 // |region| and then add up the |data_offset| displacement. 40 int64 aligned_start = 0; 41 int64 aligned_size = 0; 42 CalculateVMAlignedBoundaries(region.offset, 43 region.size, 44 &aligned_start, 45 &aligned_size, 46 &data_offset); 47 48 // Ensure that the casts in the mmap call below are sane. 49 if (aligned_start < 0 || aligned_size < 0 || 50 aligned_start > std::numeric_limits<off_t>::max() || 51 static_cast<uint64>(aligned_size) > 52 std::numeric_limits<size_t>::max() || 53 static_cast<uint64>(region.size) > std::numeric_limits<size_t>::max()) { 54 DLOG(ERROR) << "Region bounds are not valid for mmap"; 55 return false; 56 } 57 58 map_start = static_cast<off_t>(aligned_start); 59 map_size = static_cast<size_t>(aligned_size); 60 length_ = static_cast<size_t>(region.size); 61 } 62 63 data_ = static_cast<uint8*>(mmap(NULL, 64 map_size, 65 PROT_READ, 66 MAP_SHARED, 67 file_.GetPlatformFile(), 68 map_start)); 69 if (data_ == MAP_FAILED) { 70 DPLOG(ERROR) << "mmap " << file_.GetPlatformFile(); 71 return false; 72 } 73 74 data_ += data_offset; 75 return true; 76 } 77 78 void MemoryMappedFile::CloseHandles() { 79 ThreadRestrictions::AssertIOAllowed(); 80 81 if (data_ != NULL) 82 munmap(data_, length_); 83 file_.Close(); 84 85 data_ = NULL; 86 length_ = 0; 87 } 88 89 } // namespace base 90