diff options
Diffstat (limited to 'ipc/glue/FileDescriptor.cpp')
-rw-r--r-- | ipc/glue/FileDescriptor.cpp | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/ipc/glue/FileDescriptor.cpp b/ipc/glue/FileDescriptor.cpp new file mode 100644 index 000000000..1a8743d86 --- /dev/null +++ b/ipc/glue/FileDescriptor.cpp @@ -0,0 +1,226 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "FileDescriptor.h" + +#include "mozilla/Assertions.h" +#include "mozilla/Move.h" +#include "nsDebug.h" + +#ifdef XP_WIN + +#include <windows.h> +#include "ProtocolUtils.h" +#define INVALID_HANDLE INVALID_HANDLE_VALUE + +#else // XP_WIN + +#include <unistd.h> + +#ifndef OS_POSIX +#define OS_POSIX +#endif + +#include "base/eintr_wrapper.h" +#define INVALID_HANDLE -1 + +#endif // XP_WIN + +using mozilla::ipc::FileDescriptor; + +FileDescriptor::FileDescriptor() + : mHandle(INVALID_HANDLE) +{ +} + +FileDescriptor::FileDescriptor(const FileDescriptor& aOther) + : mHandle(INVALID_HANDLE) +{ + Assign(aOther); +} + +FileDescriptor::FileDescriptor(FileDescriptor&& aOther) + : mHandle(INVALID_HANDLE) +{ + *this = mozilla::Move(aOther); +} + +FileDescriptor::FileDescriptor(PlatformHandleType aHandle) + : mHandle(INVALID_HANDLE) +{ + mHandle = Clone(aHandle); +} + +FileDescriptor::FileDescriptor(const IPDLPrivate&, const PickleType& aPickle) + : mHandle(INVALID_HANDLE) +{ +#ifdef XP_WIN + mHandle = aPickle; +#else + mHandle = aPickle.fd; +#endif +} + +FileDescriptor::~FileDescriptor() +{ + Close(); +} + +FileDescriptor& +FileDescriptor::operator=(const FileDescriptor& aOther) +{ + if (this != &aOther) { + Assign(aOther); + } + return *this; +} + +FileDescriptor& +FileDescriptor::operator=(FileDescriptor&& aOther) +{ + if (this != &aOther) { + Close(); + mHandle = aOther.mHandle; + aOther.mHandle = INVALID_HANDLE; + } + return *this; +} + +bool +FileDescriptor::IsValid() const +{ + return IsValid(mHandle); +} + +void +FileDescriptor::Assign(const FileDescriptor& aOther) +{ + Close(); + mHandle = Clone(aOther.mHandle); +} + +void +FileDescriptor::Close() +{ + Close(mHandle); + mHandle = INVALID_HANDLE; +} + +FileDescriptor::PickleType +FileDescriptor::ShareTo(const FileDescriptor::IPDLPrivate&, + FileDescriptor::ProcessId aTargetPid) const +{ + PlatformHandleType newHandle; +#ifdef XP_WIN + if (IsValid()) { + if (mozilla::ipc::DuplicateHandle(mHandle, aTargetPid, &newHandle, 0, + DUPLICATE_SAME_ACCESS)) { + return newHandle; + } + NS_WARNING("Failed to duplicate file handle for other process!"); + } + return INVALID_HANDLE; +#else // XP_WIN + if (IsValid()) { + newHandle = dup(mHandle); + if (IsValid(newHandle)) { + return base::FileDescriptor(newHandle, /* auto_close */ true); + } + NS_WARNING("Failed to duplicate file handle for other process!"); + } + return base::FileDescriptor(); +#endif + + MOZ_CRASH("Must not get here!"); +} + +FileDescriptor::UniquePlatformHandle +FileDescriptor::ClonePlatformHandle() const +{ + return UniquePlatformHandle(Clone(mHandle)); +} + +bool +FileDescriptor::operator==(const FileDescriptor& aOther) const +{ + return mHandle == aOther.mHandle; +} + +// static +bool +FileDescriptor::IsValid(PlatformHandleType aHandle) +{ + return aHandle != INVALID_HANDLE; +} + +// static +FileDescriptor::PlatformHandleType +FileDescriptor::Clone(PlatformHandleType aHandle) +{ + if (!IsValid(aHandle)) { + return INVALID_HANDLE; + } + FileDescriptor::PlatformHandleType newHandle; +#ifdef XP_WIN + if (::DuplicateHandle(GetCurrentProcess(), aHandle, GetCurrentProcess(), + &newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { +#else // XP_WIN + if ((newHandle = dup(aHandle)) != INVALID_HANDLE) { +#endif + return newHandle; + } + NS_WARNING("Failed to duplicate file handle for current process!"); + return INVALID_HANDLE; +} + +// static +void +FileDescriptor::Close(PlatformHandleType aHandle) +{ + if (IsValid(aHandle)) { +#ifdef XP_WIN + if (!CloseHandle(aHandle)) { + NS_WARNING("Failed to close file handle for current process!"); + } +#else // XP_WIN + HANDLE_EINTR(close(aHandle)); +#endif + } +} + +FileDescriptor::PlatformHandleHelper::PlatformHandleHelper(FileDescriptor::PlatformHandleType aHandle) + :mHandle(aHandle) +{ +} + +FileDescriptor::PlatformHandleHelper::PlatformHandleHelper(std::nullptr_t) + :mHandle(INVALID_HANDLE) +{ +} + +bool +FileDescriptor::PlatformHandleHelper::operator!=(std::nullptr_t) const +{ + return mHandle != INVALID_HANDLE; +} + +FileDescriptor::PlatformHandleHelper::operator FileDescriptor::PlatformHandleType () const +{ + return mHandle; +} + +#ifdef XP_WIN +FileDescriptor::PlatformHandleHelper::operator std::intptr_t () const +{ + return reinterpret_cast<std::intptr_t>(mHandle); +} +#endif + +void +FileDescriptor::PlatformHandleDeleter::operator()(FileDescriptor::PlatformHandleHelper aHelper) +{ + FileDescriptor::Close(aHelper); +} |