• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter 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 "flutter/fml/mapping.h"
6 
7 #include <fcntl.h>
8 #include <sys/mman.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 
12 #include <type_traits>
13 
14 #include "flutter/fml/build_config.h"
15 #include "flutter/fml/eintr_wrapper.h"
16 #include "flutter/fml/unique_fd.h"
17 
18 namespace fml {
19 
ToPosixProtectionFlags(std::initializer_list<FileMapping::Protection> protection_flags)20 static int ToPosixProtectionFlags(
21     std::initializer_list<FileMapping::Protection> protection_flags) {
22   int flags = 0;
23   for (auto protection : protection_flags) {
24     switch (protection) {
25       case FileMapping::Protection::kRead:
26         flags |= PROT_READ;
27         break;
28       case FileMapping::Protection::kWrite:
29         flags |= PROT_WRITE;
30         break;
31       case FileMapping::Protection::kExecute:
32         flags |= PROT_READ | PROT_EXEC;
33         break;
34     }
35   }
36   return flags;
37 }
38 
IsWritable(std::initializer_list<FileMapping::Protection> protection_flags)39 static bool IsWritable(
40     std::initializer_list<FileMapping::Protection> protection_flags) {
41   for (auto protection : protection_flags) {
42     if (protection == FileMapping::Protection::kWrite) {
43       return true;
44     }
45   }
46   return false;
47 }
48 
49 Mapping::Mapping() = default;
50 
51 Mapping::~Mapping() = default;
52 
FileMapping(const fml::UniqueFD & handle,std::initializer_list<Protection> protection)53 FileMapping::FileMapping(const fml::UniqueFD& handle,
54                          std::initializer_list<Protection> protection)
55     : size_(0), mapping_(nullptr) {
56   if (!handle.is_valid()) {
57     return;
58   }
59 
60   struct stat stat_buffer = {};
61 
62   if (::fstat(handle.get(), &stat_buffer) != 0) {
63     return;
64   }
65 
66   if (stat_buffer.st_size == 0) {
67     valid_ = true;
68     return;
69   }
70 
71   const auto is_writable = IsWritable(protection);
72 
73   auto* mapping =
74       ::mmap(nullptr, stat_buffer.st_size, ToPosixProtectionFlags(protection),
75              is_writable ? MAP_SHARED : MAP_PRIVATE, handle.get(), 0);
76 
77   if (mapping == MAP_FAILED) {
78     return;
79   }
80 
81   mapping_ = static_cast<uint8_t*>(mapping);
82   size_ = stat_buffer.st_size;
83   valid_ = true;
84   if (is_writable) {
85     mutable_mapping_ = mapping_;
86   }
87 }
88 
~FileMapping()89 FileMapping::~FileMapping() {
90   if (mapping_ != nullptr) {
91     ::munmap(mapping_, size_);
92   }
93 }
94 
GetSize() const95 size_t FileMapping::GetSize() const {
96   return size_;
97 }
98 
GetMapping() const99 const uint8_t* FileMapping::GetMapping() const {
100   return mapping_;
101 }
102 
IsValid() const103 bool FileMapping::IsValid() const {
104   return valid_;
105 }
106 
107 }  // namespace fml
108