/src/mozilla-central/ipc/glue/FileDescriptor.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
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 "FileDescriptor.h" |
8 | | |
9 | | #include "mozilla/Assertions.h" |
10 | | #include "mozilla/Move.h" |
11 | | #include "nsDebug.h" |
12 | | |
13 | | #ifdef XP_WIN |
14 | | |
15 | | #include <windows.h> |
16 | | #include "ProtocolUtils.h" |
17 | | #define INVALID_HANDLE INVALID_HANDLE_VALUE |
18 | | |
19 | | #else // XP_WIN |
20 | | |
21 | | #include <unistd.h> |
22 | | |
23 | | #ifndef OS_POSIX |
24 | | #define OS_POSIX |
25 | | #endif |
26 | | |
27 | | #include "base/eintr_wrapper.h" |
28 | 0 | #define INVALID_HANDLE -1 |
29 | | |
30 | | #endif // XP_WIN |
31 | | |
32 | | namespace mozilla { |
33 | | namespace ipc { |
34 | | |
35 | | FileDescriptor::FileDescriptor() |
36 | | : mHandle(INVALID_HANDLE) |
37 | 0 | { |
38 | 0 | } |
39 | | |
40 | | FileDescriptor::FileDescriptor(const FileDescriptor& aOther) |
41 | | : mHandle(INVALID_HANDLE) |
42 | 0 | { |
43 | 0 | Assign(aOther); |
44 | 0 | } |
45 | | |
46 | | FileDescriptor::FileDescriptor(FileDescriptor&& aOther) |
47 | | : mHandle(INVALID_HANDLE) |
48 | 0 | { |
49 | 0 | *this = std::move(aOther); |
50 | 0 | } |
51 | | |
52 | | FileDescriptor::FileDescriptor(PlatformHandleType aHandle) |
53 | | : mHandle(INVALID_HANDLE) |
54 | 0 | { |
55 | 0 | mHandle = Clone(aHandle); |
56 | 0 | } |
57 | | |
58 | | FileDescriptor::FileDescriptor(const IPDLPrivate&, const PickleType& aPickle) |
59 | | : mHandle(INVALID_HANDLE) |
60 | 0 | { |
61 | | #ifdef XP_WIN |
62 | | mHandle = aPickle; |
63 | | #else |
64 | | mHandle = aPickle.fd; |
65 | 0 | #endif |
66 | 0 | } |
67 | | |
68 | | FileDescriptor::~FileDescriptor() |
69 | 0 | { |
70 | 0 | Close(); |
71 | 0 | } |
72 | | |
73 | | FileDescriptor& |
74 | | FileDescriptor::operator=(const FileDescriptor& aOther) |
75 | 0 | { |
76 | 0 | if (this != &aOther) { |
77 | 0 | Assign(aOther); |
78 | 0 | } |
79 | 0 | return *this; |
80 | 0 | } |
81 | | |
82 | | FileDescriptor& |
83 | | FileDescriptor::operator=(FileDescriptor&& aOther) |
84 | 0 | { |
85 | 0 | if (this != &aOther) { |
86 | 0 | Close(); |
87 | 0 | mHandle = aOther.mHandle; |
88 | 0 | aOther.mHandle = INVALID_HANDLE; |
89 | 0 | } |
90 | 0 | return *this; |
91 | 0 | } |
92 | | |
93 | | bool |
94 | | FileDescriptor::IsValid() const |
95 | 0 | { |
96 | 0 | return IsValid(mHandle); |
97 | 0 | } |
98 | | |
99 | | void |
100 | | FileDescriptor::Assign(const FileDescriptor& aOther) |
101 | 0 | { |
102 | 0 | Close(); |
103 | 0 | mHandle = Clone(aOther.mHandle); |
104 | 0 | } |
105 | | |
106 | | void |
107 | | FileDescriptor::Close() |
108 | 0 | { |
109 | 0 | Close(mHandle); |
110 | 0 | mHandle = INVALID_HANDLE; |
111 | 0 | } |
112 | | |
113 | | FileDescriptor::PickleType |
114 | | FileDescriptor::ShareTo(const FileDescriptor::IPDLPrivate&, |
115 | | FileDescriptor::ProcessId aTargetPid) const |
116 | 0 | { |
117 | 0 | PlatformHandleType newHandle; |
118 | | #ifdef XP_WIN |
119 | | if (IsValid()) { |
120 | | if (mozilla::ipc::DuplicateHandle(mHandle, aTargetPid, &newHandle, 0, |
121 | | DUPLICATE_SAME_ACCESS)) { |
122 | | return newHandle; |
123 | | } |
124 | | NS_WARNING("Failed to duplicate file handle for other process!"); |
125 | | } |
126 | | return INVALID_HANDLE; |
127 | | #else // XP_WIN |
128 | 0 | if (IsValid()) { |
129 | 0 | newHandle = dup(mHandle); |
130 | 0 | if (IsValid(newHandle)) { |
131 | 0 | return base::FileDescriptor(newHandle, /* auto_close */ true); |
132 | 0 | } |
133 | 0 | NS_WARNING("Failed to duplicate file handle for other process!"); |
134 | 0 | } |
135 | 0 | return base::FileDescriptor(); |
136 | 0 | #endif |
137 | 0 |
|
138 | 0 | MOZ_CRASH("Must not get here!"); |
139 | 0 | } |
140 | | |
141 | | FileDescriptor::UniquePlatformHandle |
142 | | FileDescriptor::ClonePlatformHandle() const |
143 | 0 | { |
144 | 0 | return UniquePlatformHandle(Clone(mHandle)); |
145 | 0 | } |
146 | | |
147 | | bool |
148 | | FileDescriptor::operator==(const FileDescriptor& aOther) const |
149 | 0 | { |
150 | 0 | return mHandle == aOther.mHandle; |
151 | 0 | } |
152 | | |
153 | | // static |
154 | | bool |
155 | | FileDescriptor::IsValid(PlatformHandleType aHandle) |
156 | 0 | { |
157 | 0 | return aHandle != INVALID_HANDLE; |
158 | 0 | } |
159 | | |
160 | | // static |
161 | | FileDescriptor::PlatformHandleType |
162 | | FileDescriptor::Clone(PlatformHandleType aHandle) |
163 | 0 | { |
164 | 0 | if (!IsValid(aHandle)) { |
165 | 0 | return INVALID_HANDLE; |
166 | 0 | } |
167 | 0 | FileDescriptor::PlatformHandleType newHandle; |
168 | | #ifdef XP_WIN |
169 | | if (::DuplicateHandle(GetCurrentProcess(), aHandle, GetCurrentProcess(), |
170 | | &newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { |
171 | | #else // XP_WIN |
172 | 0 | if ((newHandle = dup(aHandle)) != INVALID_HANDLE) { |
173 | 0 | #endif |
174 | 0 | return newHandle; |
175 | 0 | } |
176 | 0 | NS_WARNING("Failed to duplicate file handle for current process!"); |
177 | 0 | return INVALID_HANDLE; |
178 | 0 | } |
179 | | |
180 | | // static |
181 | | void |
182 | | FileDescriptor::Close(PlatformHandleType aHandle) |
183 | 0 | { |
184 | 0 | if (IsValid(aHandle)) { |
185 | | #ifdef XP_WIN |
186 | | if (!CloseHandle(aHandle)) { |
187 | | NS_WARNING("Failed to close file handle for current process!"); |
188 | | } |
189 | | #else // XP_WIN |
190 | 0 | IGNORE_EINTR(close(aHandle)); |
191 | 0 | #endif |
192 | 0 | } |
193 | 0 | } |
194 | | |
195 | | FileDescriptor::PlatformHandleHelper::PlatformHandleHelper(FileDescriptor::PlatformHandleType aHandle) |
196 | | :mHandle(aHandle) |
197 | 0 | { |
198 | 0 | } |
199 | | |
200 | | FileDescriptor::PlatformHandleHelper::PlatformHandleHelper(std::nullptr_t) |
201 | | :mHandle(INVALID_HANDLE) |
202 | 0 | { |
203 | 0 | } |
204 | | |
205 | | bool |
206 | | FileDescriptor::PlatformHandleHelper::operator!=(std::nullptr_t) const |
207 | 0 | { |
208 | 0 | return mHandle != INVALID_HANDLE; |
209 | 0 | } |
210 | | |
211 | | FileDescriptor::PlatformHandleHelper::operator FileDescriptor::PlatformHandleType () const |
212 | 0 | { |
213 | 0 | return mHandle; |
214 | 0 | } |
215 | | |
216 | | #ifdef XP_WIN |
217 | | FileDescriptor::PlatformHandleHelper::operator std::intptr_t () const |
218 | | { |
219 | | return reinterpret_cast<std::intptr_t>(mHandle); |
220 | | } |
221 | | #endif |
222 | | |
223 | | void |
224 | | FileDescriptor::PlatformHandleDeleter::operator()(FileDescriptor::PlatformHandleHelper aHelper) |
225 | 0 | { |
226 | 0 | FileDescriptor::Close(aHelper); |
227 | 0 | } |
228 | | |
229 | | void |
230 | | IPDLParamTraits<FileDescriptor>::Write(IPC::Message* aMsg, |
231 | | IProtocol* aActor, |
232 | | const FileDescriptor& aParam) |
233 | 0 | { |
234 | 0 | FileDescriptor::PickleType pfd = |
235 | 0 | aParam.ShareTo(FileDescriptor::IPDLPrivate(), aActor->OtherPid()); |
236 | 0 | WriteIPDLParam(aMsg, aActor, pfd); |
237 | 0 | } |
238 | | |
239 | | bool |
240 | | IPDLParamTraits<FileDescriptor>::Read(const IPC::Message* aMsg, |
241 | | PickleIterator* aIter, |
242 | | IProtocol* aActor, |
243 | | FileDescriptor* aResult) |
244 | 0 | { |
245 | 0 | FileDescriptor::PickleType pfd; |
246 | 0 | if (!ReadIPDLParam(aMsg, aIter, aActor, &pfd)) { |
247 | 0 | return false; |
248 | 0 | } |
249 | 0 | |
250 | 0 | *aResult = FileDescriptor(FileDescriptor::IPDLPrivate(), pfd); |
251 | 0 | if (!aResult->IsValid()) { |
252 | 0 | printf_stderr("IPDL protocol Error: Received an invalid file descriptor\n"); |
253 | 0 | } |
254 | 0 | return true; |
255 | 0 | } |
256 | | |
257 | | } // namespace ipc |
258 | | } // namespace mozilla |