Coverage Report

Created: 2018-09-25 14:53

/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