/src/mozilla-central/js/xpconnect/loader/AutoMemMap.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* vim: set ts=8 sts=4 et sw=4 tw=99: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "AutoMemMap.h" |
8 | | #include "ScriptPreloader-inl.h" |
9 | | |
10 | | #include "mozilla/Unused.h" |
11 | | #include "mozilla/ipc/FileDescriptor.h" |
12 | | #include "nsIFile.h" |
13 | | |
14 | | #include <private/pprio.h> |
15 | | |
16 | | namespace mozilla { |
17 | | namespace loader { |
18 | | |
19 | | using namespace mozilla::ipc; |
20 | | |
21 | | AutoMemMap::~AutoMemMap() |
22 | 0 | { |
23 | 0 | reset(); |
24 | 0 | } |
25 | | |
26 | | FileDescriptor |
27 | | AutoMemMap::cloneFileDescriptor() const |
28 | 0 | { |
29 | 0 | if (fd.get()) { |
30 | 0 | auto handle = FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(fd.get())); |
31 | 0 | return FileDescriptor(handle); |
32 | 0 | } |
33 | 0 | return FileDescriptor(); |
34 | 0 | } |
35 | | |
36 | | Result<Ok, nsresult> |
37 | | AutoMemMap::init(nsIFile* file, int flags, int mode, PRFileMapProtect prot) |
38 | 0 | { |
39 | 0 | MOZ_ASSERT(!fd); |
40 | 0 |
|
41 | 0 | MOZ_TRY(file->OpenNSPRFileDesc(flags, mode, &fd.rwget())); |
42 | 0 |
|
43 | 0 | return initInternal(prot); |
44 | 0 | } |
45 | | |
46 | | Result<Ok, nsresult> |
47 | | AutoMemMap::init(const FileDescriptor& file, PRFileMapProtect prot, |
48 | | size_t expectedSize) |
49 | 0 | { |
50 | 0 | MOZ_ASSERT(!fd); |
51 | 0 | if (!file.IsValid()) { |
52 | 0 | return Err(NS_ERROR_INVALID_ARG); |
53 | 0 | } |
54 | 0 | |
55 | 0 | auto handle = file.ClonePlatformHandle(); |
56 | 0 |
|
57 | 0 | fd = PR_ImportFile(PROsfd(handle.get())); |
58 | 0 | if (!fd) { |
59 | 0 | return Err(NS_ERROR_FAILURE); |
60 | 0 | } |
61 | 0 | Unused << handle.release(); |
62 | 0 |
|
63 | 0 | return initInternal(prot, expectedSize); |
64 | 0 | } |
65 | | |
66 | | Result<Ok, nsresult> |
67 | | AutoMemMap::initInternal(PRFileMapProtect prot, size_t expectedSize) |
68 | 0 | { |
69 | 0 | MOZ_ASSERT(!fileMap); |
70 | 0 | MOZ_ASSERT(!addr); |
71 | 0 |
|
72 | 0 | PRFileInfo64 fileInfo; |
73 | 0 | MOZ_TRY(PR_GetOpenFileInfo64(fd.get(), &fileInfo)); |
74 | 0 |
|
75 | 0 | if (fileInfo.size > UINT32_MAX) { |
76 | 0 | return Err(NS_ERROR_INVALID_ARG); |
77 | 0 | } |
78 | 0 | |
79 | 0 | fileMap = PR_CreateFileMap(fd, 0, prot); |
80 | 0 | if (!fileMap) { |
81 | 0 | return Err(NS_ERROR_FAILURE); |
82 | 0 | } |
83 | 0 | |
84 | 0 | size_ = fileInfo.size; |
85 | 0 | // The memory region size passed in certain IPC messages isn't necessary on |
86 | 0 | // Unix-like systems, since we can always stat the file descriptor to |
87 | 0 | // determine it accurately. But since we have it, anyway, sanity check that |
88 | 0 | // it matches the size returned by the stat. |
89 | 0 | MOZ_ASSERT_IF(expectedSize > 0, size_ == expectedSize); |
90 | 0 |
|
91 | 0 | addr = PR_MemMap(fileMap, 0, size_); |
92 | 0 | if (!addr) { |
93 | 0 | return Err(NS_ERROR_FAILURE); |
94 | 0 | } |
95 | 0 | |
96 | 0 | return Ok(); |
97 | 0 | } |
98 | | |
99 | | #ifdef XP_WIN |
100 | | |
101 | | Result<Ok, nsresult> |
102 | | AutoMemMap::initWithHandle(const FileDescriptor& file, size_t size, PRFileMapProtect prot) |
103 | | { |
104 | | MOZ_ASSERT(!fd); |
105 | | MOZ_ASSERT(!handle_); |
106 | | if (!file.IsValid()) { |
107 | | return Err(NS_ERROR_INVALID_ARG); |
108 | | } |
109 | | |
110 | | handle_ = file.ClonePlatformHandle().release(); |
111 | | |
112 | | MOZ_ASSERT(!addr); |
113 | | |
114 | | size_ = size; |
115 | | |
116 | | addr = MapViewOfFile( |
117 | | handle_, |
118 | | prot == PR_PROT_READONLY ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, |
119 | | 0, 0, size); |
120 | | |
121 | | return Ok(); |
122 | | } |
123 | | |
124 | | FileDescriptor |
125 | | AutoMemMap::cloneHandle() const |
126 | | { |
127 | | return FileDescriptor(handle_); |
128 | | } |
129 | | |
130 | | #else |
131 | | |
132 | | Result<Ok, nsresult> |
133 | | AutoMemMap::initWithHandle(const FileDescriptor& file, size_t size, PRFileMapProtect prot) |
134 | 0 | { |
135 | 0 | return init(file, prot); |
136 | 0 | } |
137 | | |
138 | | FileDescriptor |
139 | | AutoMemMap::cloneHandle() const |
140 | 0 | { |
141 | 0 | return cloneFileDescriptor(); |
142 | 0 | } |
143 | | |
144 | | #endif |
145 | | |
146 | | void |
147 | | AutoMemMap::reset() |
148 | 0 | { |
149 | 0 | if (addr && !persistent_) { |
150 | 0 | Unused << NS_WARN_IF(PR_MemUnmap(addr, size()) != PR_SUCCESS); |
151 | 0 | addr = nullptr; |
152 | 0 | } |
153 | 0 | if (fileMap) { |
154 | 0 | Unused << NS_WARN_IF(PR_CloseFileMap(fileMap) != PR_SUCCESS); |
155 | 0 | fileMap = nullptr; |
156 | 0 | } |
157 | | #ifdef XP_WIN |
158 | | if (handle_) { |
159 | | CloseHandle(handle_); |
160 | | handle_ = nullptr; |
161 | | } |
162 | | #endif |
163 | | fd.dispose(); |
164 | 0 | } |
165 | | |
166 | | } // namespace loader |
167 | | } // namespace mozilla |