• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,Access access)33 bool MemoryMappedFile::Initialize(const FilePath& file_name, Access access) {
34   if (IsValid())
35     return false;
36 
37   uint32_t flags = 0;
38   switch (access) {
39     case READ_ONLY:
40       flags = File::FLAG_OPEN | File::FLAG_READ;
41       break;
42     case READ_WRITE:
43       flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE;
44       break;
45     case READ_WRITE_EXTEND:
46       // Can't open with "extend" because no maximum size is known.
47       NOTREACHED();
48   }
49   file_.Initialize(file_name, flags);
50 
51   if (!file_.IsValid()) {
52     DLOG(ERROR) << "Couldn't open " << file_name.AsUTF8Unsafe();
53     return false;
54   }
55 
56   if (!MapFileRegionToMemory(Region::kWholeFile, access)) {
57     CloseHandles();
58     return false;
59   }
60 
61   return true;
62 }
63 
Initialize(File file,Access access)64 bool MemoryMappedFile::Initialize(File file, Access access) {
65   DCHECK_NE(READ_WRITE_EXTEND, access);
66   return Initialize(std::move(file), Region::kWholeFile, access);
67 }
68 
Initialize(File file,const Region & region,Access access)69 bool MemoryMappedFile::Initialize(File file,
70                                   const Region& region,
71                                   Access access) {
72   switch (access) {
73     case READ_WRITE_EXTEND:
74       // Ensure that the extended size is within limits of File.
75       if (region.size > std::numeric_limits<int64_t>::max() - region.offset) {
76         DLOG(ERROR) << "Region bounds exceed maximum for base::File.";
77         return false;
78       }
79       // Fall through.
80     case READ_ONLY:
81     case READ_WRITE:
82       // Ensure that the region values are valid.
83       if (region.offset < 0 || region.size < 0) {
84         DLOG(ERROR) << "Region bounds are not valid.";
85         return false;
86       }
87       break;
88   }
89 
90   if (IsValid())
91     return false;
92 
93   if (region != Region::kWholeFile) {
94     DCHECK_GE(region.offset, 0);
95     DCHECK_GT(region.size, 0);
96   }
97 
98   file_ = std::move(file);
99 
100   if (!MapFileRegionToMemory(region, access)) {
101     CloseHandles();
102     return false;
103   }
104 
105   return true;
106 }
107 
IsValid() const108 bool MemoryMappedFile::IsValid() const {
109   return data_ != NULL;
110 }
111 
112 // static
CalculateVMAlignedBoundaries(int64_t start,int64_t size,int64_t * aligned_start,int64_t * aligned_size,int32_t * offset)113 void MemoryMappedFile::CalculateVMAlignedBoundaries(int64_t start,
114                                                     int64_t size,
115                                                     int64_t* aligned_start,
116                                                     int64_t* aligned_size,
117                                                     int32_t* offset) {
118   // Sadly, on Windows, the mmap alignment is not just equal to the page size.
119   const int64_t mask =
120       static_cast<int64_t>(SysInfo::VMAllocationGranularity()) - 1;
121   DCHECK_LT(mask, std::numeric_limits<int32_t>::max());
122   *offset = start & mask;
123   *aligned_start = start & ~mask;
124   *aligned_size = (size + *offset + mask) & ~mask;
125 }
126 #endif
127 
128 }  // namespace base
129