• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <sys/mman.h>
17 #include <sys/stat.h>
18 
19 #include "aemu/base/EintrWrapper.h"
20 #include "aemu/base/memory/SharedMemory.h"
21 #include "aemu/base/files/PathUtils.h"
22 #ifndef _MSC_VER
23 #include <unistd.h>
24 #endif
25 
26 namespace android {
27 namespace base {
28 
SharedMemory(const std::string & name,size_t size)29 SharedMemory::SharedMemory(const std::string& name, size_t size) : mSize(size) {
30     const std::string& kFileUri = "file://";
31     if (name.find(kFileUri, 0) == 0) {
32         mShareType = ShareType::FILE_BACKED;
33         auto path = name.substr(kFileUri.size());
34         mName = PathUtils::recompose(PathUtils::decompose(std::move(path)));
35     } else {
36         mShareType = ShareType::SHARED_MEMORY;
37         mName = name;
38     }
39 }
40 
create(mode_t mode)41 int SharedMemory::create(mode_t mode) {
42     return openInternal(O_CREAT | O_RDWR, mode);
43 }
44 
createNoMapping(mode_t mode)45 int SharedMemory::createNoMapping(mode_t mode) {
46     return openInternal(O_CREAT | O_RDWR, mode, false /* no mapping */);
47 }
48 
open(AccessMode access)49 int SharedMemory::open(AccessMode access) {
50     int oflag = O_RDONLY;
51     int mode = 0400;
52     if (access == AccessMode::READ_WRITE) {
53         oflag = O_RDWR;
54         mode = 0600;
55     }
56     return openInternal(oflag, mode);
57 }
58 
close(bool forceDestroy)59 void SharedMemory::close(bool forceDestroy) {
60     if (mAddr != unmappedMemory()) {
61         munmap(mAddr, mSize);
62         mAddr = unmappedMemory();
63     }
64     if (mFd) {
65         ::close(mFd);
66         mFd = invalidHandle();
67     }
68 
69     assert(!isOpen());
70     if (forceDestroy || mCreate) {
71         if (mShareType == ShareType::FILE_BACKED) {
72             remove(mName.c_str());
73         } else {
74 #if !defined(__BIONIC__)
75             shm_unlink(mName.c_str());
76 #endif
77         }
78     }
79 }
80 
isOpen() const81 bool SharedMemory::isOpen() const {
82     return mFd != invalidHandle();
83 }
84 
openInternal(int oflag,int mode,bool doMapping)85 int SharedMemory::openInternal(int oflag, int mode, bool doMapping) {
86     if (isOpen()) {
87         return EEXIST;
88     }
89 
90     int err = 0;
91     struct stat sb;
92     if (mShareType == ShareType::SHARED_MEMORY) {
93 #if !defined(__BIONIC__)
94         mFd = shm_open(mName.c_str(), oflag, mode);
95 #else
96         return ENOTTY;
97 #endif
98     } else {
99         mFd = ::open(mName.c_str(), oflag, mode);
100         // Make sure the file can hold at least mSize bytes..
101         struct stat stat;
102         if (!fstat(mFd, &stat) && stat.st_size < mSize) {
103             err = ftruncate(mFd, mSize);
104         }
105     }
106     if (mFd == -1 || err) {
107         err = -errno;
108         close();
109         return err;
110     }
111 
112     if (oflag & O_CREAT) {
113         if (HANDLE_EINTR(fstat(mFd, &sb)) == -1) {
114             err = -errno;
115             close();
116             return err;
117         }
118 
119         // Only increase size, as we don't want to yank away memory
120         // from another process.
121         if (mSize > sb.st_size && HANDLE_EINTR(ftruncate(mFd, mSize)) == -1) {
122             err = -errno;
123             close();
124             return err;
125         }
126     }
127 
128     if (doMapping) {
129         int mapFlags = PROT_READ;
130         if (oflag & O_RDWR || oflag & O_CREAT) {
131             mapFlags |= PROT_WRITE;
132         }
133 
134         mAddr = mmap(nullptr, mSize, mapFlags, MAP_SHARED, mFd, 0);
135         if (mAddr == unmappedMemory()) {
136             err = -errno;
137             close();
138             return err;
139         }
140     }
141 
142     mCreate |= (oflag & O_CREAT);
143     assert(isOpen());
144     return 0;
145 }
146 }  // namespace base
147 }  // namespace android
148