Line data Source code
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 : #define INVALID_HANDLE -1
29 :
30 : #endif // XP_WIN
31 :
32 : using mozilla::ipc::FileDescriptor;
33 :
34 5 : FileDescriptor::FileDescriptor()
35 5 : : mHandle(INVALID_HANDLE)
36 : {
37 5 : }
38 :
39 4 : FileDescriptor::FileDescriptor(const FileDescriptor& aOther)
40 4 : : mHandle(INVALID_HANDLE)
41 : {
42 4 : Assign(aOther);
43 4 : }
44 :
45 0 : FileDescriptor::FileDescriptor(FileDescriptor&& aOther)
46 0 : : mHandle(INVALID_HANDLE)
47 : {
48 0 : *this = mozilla::Move(aOther);
49 0 : }
50 :
51 4 : FileDescriptor::FileDescriptor(PlatformHandleType aHandle)
52 4 : : mHandle(INVALID_HANDLE)
53 : {
54 4 : mHandle = Clone(aHandle);
55 4 : }
56 :
57 3 : FileDescriptor::FileDescriptor(const IPDLPrivate&, const PickleType& aPickle)
58 3 : : mHandle(INVALID_HANDLE)
59 : {
60 : #ifdef XP_WIN
61 : mHandle = aPickle;
62 : #else
63 3 : mHandle = aPickle.fd;
64 : #endif
65 3 : }
66 :
67 32 : FileDescriptor::~FileDescriptor()
68 : {
69 16 : Close();
70 16 : }
71 :
72 : FileDescriptor&
73 5 : FileDescriptor::operator=(const FileDescriptor& aOther)
74 : {
75 5 : if (this != &aOther) {
76 5 : Assign(aOther);
77 : }
78 5 : return *this;
79 : }
80 :
81 : FileDescriptor&
82 0 : FileDescriptor::operator=(FileDescriptor&& aOther)
83 : {
84 0 : if (this != &aOther) {
85 0 : Close();
86 0 : mHandle = aOther.mHandle;
87 0 : aOther.mHandle = INVALID_HANDLE;
88 : }
89 0 : return *this;
90 : }
91 :
92 : bool
93 12 : FileDescriptor::IsValid() const
94 : {
95 12 : return IsValid(mHandle);
96 : }
97 :
98 : void
99 9 : FileDescriptor::Assign(const FileDescriptor& aOther)
100 : {
101 9 : Close();
102 9 : mHandle = Clone(aOther.mHandle);
103 9 : }
104 :
105 : void
106 25 : FileDescriptor::Close()
107 : {
108 25 : Close(mHandle);
109 25 : mHandle = INVALID_HANDLE;
110 25 : }
111 :
112 : FileDescriptor::PickleType
113 4 : FileDescriptor::ShareTo(const FileDescriptor::IPDLPrivate&,
114 : FileDescriptor::ProcessId aTargetPid) const
115 : {
116 : PlatformHandleType newHandle;
117 : #ifdef XP_WIN
118 : if (IsValid()) {
119 : if (mozilla::ipc::DuplicateHandle(mHandle, aTargetPid, &newHandle, 0,
120 : DUPLICATE_SAME_ACCESS)) {
121 : return newHandle;
122 : }
123 : NS_WARNING("Failed to duplicate file handle for other process!");
124 : }
125 : return INVALID_HANDLE;
126 : #else // XP_WIN
127 4 : if (IsValid()) {
128 4 : newHandle = dup(mHandle);
129 4 : if (IsValid(newHandle)) {
130 4 : return base::FileDescriptor(newHandle, /* auto_close */ true);
131 : }
132 0 : NS_WARNING("Failed to duplicate file handle for other process!");
133 : }
134 0 : return base::FileDescriptor();
135 : #endif
136 :
137 : MOZ_CRASH("Must not get here!");
138 : }
139 :
140 : FileDescriptor::UniquePlatformHandle
141 3 : FileDescriptor::ClonePlatformHandle() const
142 : {
143 3 : return UniquePlatformHandle(Clone(mHandle));
144 : }
145 :
146 : bool
147 0 : FileDescriptor::operator==(const FileDescriptor& aOther) const
148 : {
149 0 : return mHandle == aOther.mHandle;
150 : }
151 :
152 : // static
153 : bool
154 57 : FileDescriptor::IsValid(PlatformHandleType aHandle)
155 : {
156 57 : return aHandle != INVALID_HANDLE;
157 : }
158 :
159 : // static
160 : FileDescriptor::PlatformHandleType
161 16 : FileDescriptor::Clone(PlatformHandleType aHandle)
162 : {
163 16 : if (!IsValid(aHandle)) {
164 2 : return INVALID_HANDLE;
165 : }
166 : FileDescriptor::PlatformHandleType newHandle;
167 : #ifdef XP_WIN
168 : if (::DuplicateHandle(GetCurrentProcess(), aHandle, GetCurrentProcess(),
169 : &newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
170 : #else // XP_WIN
171 14 : if ((newHandle = dup(aHandle)) != INVALID_HANDLE) {
172 : #endif
173 14 : return newHandle;
174 : }
175 0 : NS_WARNING("Failed to duplicate file handle for current process!");
176 0 : return INVALID_HANDLE;
177 : }
178 :
179 : // static
180 : void
181 25 : FileDescriptor::Close(PlatformHandleType aHandle)
182 : {
183 25 : if (IsValid(aHandle)) {
184 : #ifdef XP_WIN
185 : if (!CloseHandle(aHandle)) {
186 : NS_WARNING("Failed to close file handle for current process!");
187 : }
188 : #else // XP_WIN
189 14 : HANDLE_EINTR(close(aHandle));
190 : #endif
191 : }
192 25 : }
193 :
194 3 : FileDescriptor::PlatformHandleHelper::PlatformHandleHelper(FileDescriptor::PlatformHandleType aHandle)
195 3 : :mHandle(aHandle)
196 : {
197 3 : }
198 :
199 6 : FileDescriptor::PlatformHandleHelper::PlatformHandleHelper(std::nullptr_t)
200 6 : :mHandle(INVALID_HANDLE)
201 : {
202 6 : }
203 :
204 : bool
205 3 : FileDescriptor::PlatformHandleHelper::operator!=(std::nullptr_t) const
206 : {
207 3 : return mHandle != INVALID_HANDLE;
208 : }
209 :
210 3 : FileDescriptor::PlatformHandleHelper::operator FileDescriptor::PlatformHandleType () const
211 : {
212 3 : return mHandle;
213 : }
214 :
215 : #ifdef XP_WIN
216 : FileDescriptor::PlatformHandleHelper::operator std::intptr_t () const
217 : {
218 : return reinterpret_cast<std::intptr_t>(mHandle);
219 : }
220 : #endif
221 :
222 : void
223 0 : FileDescriptor::PlatformHandleDeleter::operator()(FileDescriptor::PlatformHandleHelper aHelper)
224 : {
225 0 : FileDescriptor::Close(aHelper);
226 0 : }
|