tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FileDescriptorUtils.cpp (2702B)


      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 "FileDescriptorUtils.h"
      8 
      9 #include "nsIEventTarget.h"
     10 
     11 #include "nsCOMPtr.h"
     12 #include "nsDebug.h"
     13 #include "nsNetCID.h"
     14 #include "nsServiceManagerUtils.h"
     15 #include "prio.h"
     16 #include "private/pprio.h"
     17 
     18 #include <errno.h>
     19 #ifdef XP_WIN
     20 #  include <io.h>
     21 #else
     22 #  include <unistd.h>
     23 #endif
     24 
     25 using mozilla::ipc::CloseFileRunnable;
     26 
     27 CloseFileRunnable::CloseFileRunnable(const FileDescriptor& aFileDescriptor)
     28    : Runnable("CloseFileRunnable"), mFileDescriptor(aFileDescriptor) {
     29  MOZ_ASSERT(aFileDescriptor.IsValid());
     30 }
     31 
     32 CloseFileRunnable::~CloseFileRunnable() {
     33  if (mFileDescriptor.IsValid()) {
     34    // It's probably safer to take the main thread IO hit here rather than leak
     35    // the file descriptor.
     36    CloseFile();
     37  }
     38 }
     39 
     40 NS_IMPL_ISUPPORTS_INHERITED0(CloseFileRunnable, Runnable)
     41 
     42 void CloseFileRunnable::Dispatch() {
     43  nsCOMPtr<nsIEventTarget> eventTarget =
     44      do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     45  NS_ENSURE_TRUE_VOID(eventTarget);
     46 
     47  nsresult rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
     48  NS_ENSURE_SUCCESS_VOID(rv);
     49 }
     50 
     51 void CloseFileRunnable::CloseFile() {
     52  // It's possible for this to happen on the main thread if the dispatch to the
     53  // stream service fails so we can't assert the thread on which we're running.
     54  mFileDescriptor = FileDescriptor();
     55 }
     56 
     57 NS_IMETHODIMP
     58 CloseFileRunnable::Run() {
     59  MOZ_ASSERT(!NS_IsMainThread());
     60 
     61  CloseFile();
     62  return NS_OK;
     63 }
     64 
     65 namespace mozilla {
     66 namespace ipc {
     67 
     68 FILE* FileDescriptorToFILE(const FileDescriptor& aDesc, const char* aOpenMode) {
     69  if (!aDesc.IsValid()) {
     70    errno = EBADF;
     71    return nullptr;
     72  }
     73  auto handle = aDesc.ClonePlatformHandle();
     74 #ifdef XP_WIN
     75  int fd = _open_osfhandle(static_cast<intptr_t>(handle.get()), 0);
     76  if (fd == -1) {
     77    return nullptr;
     78  }
     79  (void)handle.release();
     80 #else
     81  int fd = handle.release();
     82 #endif
     83  FILE* file = fdopen(fd, aOpenMode);
     84  if (!file) {
     85    int saved_errno = errno;
     86    close(fd);
     87    errno = saved_errno;
     88  }
     89  return file;
     90 }
     91 
     92 FileDescriptor FILEToFileDescriptor(FILE* aStream) {
     93  if (!aStream) {
     94    errno = EBADF;
     95    return FileDescriptor();
     96  }
     97 #ifdef XP_WIN
     98  int fd = _fileno(aStream);
     99  if (fd == -1) {
    100    return FileDescriptor();
    101  }
    102  return FileDescriptor(reinterpret_cast<HANDLE>(_get_osfhandle(fd)));
    103 #else
    104  return FileDescriptor(fileno(aStream));
    105 #endif
    106 }
    107 
    108 }  // namespace ipc
    109 }  // namespace mozilla