FileDescriptor.cpp (3245B)
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/ipc/ProtocolMessageUtils.h" 10 #include "nsDebug.h" 11 12 #ifdef XP_WIN 13 # include <windows.h> 14 # include "ProtocolUtils.h" 15 #else // XP_WIN 16 # include <unistd.h> 17 #endif // XP_WIN 18 19 namespace mozilla { 20 namespace ipc { 21 22 FileDescriptor::FileDescriptor() = default; 23 24 FileDescriptor::FileDescriptor(const FileDescriptor& aOther) 25 : mHandle(Clone(aOther.mHandle.get())) {} 26 27 FileDescriptor::FileDescriptor(FileDescriptor&& aOther) 28 : mHandle(std::move(aOther.mHandle)) {} 29 30 FileDescriptor::FileDescriptor(PlatformHandleType aHandle) 31 : mHandle(Clone(aHandle)) {} 32 33 FileDescriptor::FileDescriptor(UniquePlatformHandle&& aHandle) 34 : mHandle(std::move(aHandle)) {} 35 36 FileDescriptor::~FileDescriptor() = default; 37 38 FileDescriptor& FileDescriptor::operator=(const FileDescriptor& aOther) { 39 if (this != &aOther) { 40 mHandle = Clone(aOther.mHandle.get()); 41 } 42 return *this; 43 } 44 45 FileDescriptor& FileDescriptor::operator=(FileDescriptor&& aOther) { 46 if (this != &aOther) { 47 mHandle = std::move(aOther.mHandle); 48 } 49 return *this; 50 } 51 52 bool FileDescriptor::IsValid() const { return mHandle != nullptr; } 53 54 FileDescriptor::UniquePlatformHandle FileDescriptor::ClonePlatformHandle() 55 const { 56 return Clone(mHandle.get()); 57 } 58 59 FileDescriptor::UniquePlatformHandle FileDescriptor::TakePlatformHandle() { 60 return UniquePlatformHandle(mHandle.release()); 61 } 62 63 bool FileDescriptor::operator==(const FileDescriptor& aOther) const { 64 return mHandle == aOther.mHandle; 65 } 66 67 // static 68 FileDescriptor::UniquePlatformHandle FileDescriptor::Clone( 69 PlatformHandleType aHandle) { 70 FileDescriptor::PlatformHandleType newHandle; 71 72 #ifdef XP_WIN 73 if (aHandle == INVALID_HANDLE_VALUE || aHandle == nullptr) { 74 return UniqueFileHandle(); 75 } 76 if (::DuplicateHandle(GetCurrentProcess(), aHandle, GetCurrentProcess(), 77 &newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { 78 return UniqueFileHandle(newHandle); 79 } 80 #else // XP_WIN 81 if (aHandle < 0) { 82 return UniqueFileHandle(); 83 } 84 newHandle = dup(aHandle); 85 if (newHandle >= 0) { 86 return UniqueFileHandle(newHandle); 87 } 88 #endif 89 NS_WARNING("Failed to duplicate file handle for current process!"); 90 return UniqueFileHandle(); 91 } 92 93 } // namespace ipc 94 } // namespace mozilla 95 96 namespace IPC { 97 98 void ParamTraits<mozilla::ipc::FileDescriptor>::Write( 99 MessageWriter* aWriter, const mozilla::ipc::FileDescriptor& aParam) { 100 WriteParam(aWriter, aParam.ClonePlatformHandle()); 101 } 102 103 bool ParamTraits<mozilla::ipc::FileDescriptor>::Read( 104 MessageReader* aReader, mozilla::ipc::FileDescriptor* aResult) { 105 mozilla::UniqueFileHandle handle; 106 if (!ReadParam(aReader, &handle)) { 107 return false; 108 } 109 110 *aResult = mozilla::ipc::FileDescriptor(std::move(handle)); 111 if (!aResult->IsValid()) { 112 printf_stderr("IPDL protocol Error: Received an invalid file descriptor\n"); 113 } 114 return true; 115 } 116 117 } // namespace IPC