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 <utility>
8 
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/sys_info.h"
12 #include "build/build_config.h"
13 
14 namespace base {
15 
16 const MemoryMappedFile::Region MemoryMappedFile::Region::kWholeFile = {0, 0};
17 
operator ==(const MemoryMappedFile::Region & other) const18 bool MemoryMappedFile::Region::operator==(
19     const MemoryMappedFile::Region& other) const {
20   return other.offset == offset && other.size == size;
21 }
22 
operator !=(const MemoryMappedFile::Region & other) const23 bool MemoryMappedFile::Region::operator!=(
24     const MemoryMappedFile::Region& other) const {
25   return other.offset != offset || other.size != size;
26 }
27 
~MemoryMappedFile()28 MemoryMappedFile::~MemoryMappedFile() {
29   CloseHandles();
30 }
31 
32 #if !defined(OS_NACL)
Initialize(const FilePath & file_name)33 bool MemoryMappedFile::Initialize(const FilePath& file_name) {
34   if (IsValid())
35     return false;
36 
37   file_.Initialize(file_name, File::FLAG_OPEN | File::FLAG_READ);
38 
39   if (!file_.IsValid()) {
40     DLOG(ERROR) << "Couldn't open " << file_name.AsUTF8Unsafe();
41     return false;
42   }
43 
44   if (!MapFileRegionToMemory(Region::kWholeFile)) {
45     CloseHandles();
46     return false;
47   }
48 
49   return true;
50 }
51 
Initialize(File file)52 bool MemoryMappedFile::Initialize(File file) {
53   return Initialize(std::move(file), Region::kWholeFile);
54 }
55 
Initialize(File file,const Region & region)56 bool MemoryMappedFile::Initialize(File file, const Region& region) {
57   if (IsValid())
58     return false;
59 
60   if (region != Region::kWholeFile) {
61     DCHECK_GE(region.offset, 0);
62     DCHECK_GT(region.size, 0);
63   }
64 
65   file_ = std::move(file);
66 
67   if (!MapFileRegionToMemory(region)) {
68     CloseHandles();
69     return false;
70   }
71 
72   return true;
73 }
74 
IsValid() const75 bool MemoryMappedFile::IsValid() const {
76   return data_ != NULL;
77 }
78 
79 // static
CalculateVMAlignedBoundaries(int64_t start,int64_t size,int64_t * aligned_start,int64_t * aligned_size,int32_t * offset)80 void MemoryMappedFile::CalculateVMAlignedBoundaries(int64_t start,
81                                                     int64_t size,
82                                                     int64_t* aligned_start,
83                                                     int64_t* aligned_size,
84                                                     int32_t* offset) {
85   // Sadly, on Windows, the mmap alignment is not just equal to the page size.
86   const int64_t mask =
87       static_cast<int64_t>(SysInfo::VMAllocationGranularity()) - 1;
88   DCHECK_LT(mask, std::numeric_limits<int32_t>::max());
89   *offset = start & mask;
90   *aligned_start = start & ~mask;
91   *aligned_size = (size + *offset + mask) & ~mask;
92 }
93 #endif
94 
95 }  // namespace base
96