ipc/chromium/src/base/file_descriptor_shuffle.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/base/file_descriptor_shuffle.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,94 @@
     1.4 +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +#include "base/file_descriptor_shuffle.h"
     1.9 +
    1.10 +#include <errno.h>
    1.11 +#include <unistd.h>
    1.12 +
    1.13 +#include "base/eintr_wrapper.h"
    1.14 +#include "base/logging.h"
    1.15 +
    1.16 +namespace base {
    1.17 +
    1.18 +bool PerformInjectiveMultimapDestructive(
    1.19 +    InjectiveMultimap* m, InjectionDelegate* delegate) {
    1.20 +  static const size_t kMaxExtraFDs = 16;
    1.21 +  int extra_fds[kMaxExtraFDs];
    1.22 +  unsigned next_extra_fd = 0;
    1.23 +
    1.24 +  // DANGER: this function may not allocate.
    1.25 +
    1.26 +  for (InjectiveMultimap::iterator i = m->begin(); i != m->end(); ++i) {
    1.27 +    int temp_fd = -1;
    1.28 +
    1.29 +    // We DCHECK the injectiveness of the mapping.
    1.30 +    for (InjectiveMultimap::iterator j = i + 1; j != m->end(); ++j) {
    1.31 +      DCHECK(i->dest != j->dest) << "Both fd " << i->source
    1.32 +          << " and " << j->source << " map to " << i->dest;
    1.33 +    }
    1.34 +
    1.35 +    const bool is_identity = i->source == i->dest;
    1.36 +
    1.37 +    for (InjectiveMultimap::iterator j = i + 1; j != m->end(); ++j) {
    1.38 +      if (!is_identity && i->dest == j->source) {
    1.39 +        if (temp_fd == -1) {
    1.40 +          if (!delegate->Duplicate(&temp_fd, i->dest))
    1.41 +            return false;
    1.42 +          if (next_extra_fd < kMaxExtraFDs) {
    1.43 +            extra_fds[next_extra_fd++] = temp_fd;
    1.44 +          } else {
    1.45 +              DLOG(ERROR) << "PerformInjectiveMultimapDestructive overflowed "
    1.46 +                          << "extra_fds. Leaking file descriptors!";
    1.47 +          }
    1.48 +        }
    1.49 +
    1.50 +        j->source = temp_fd;
    1.51 +        j->close = false;
    1.52 +      }
    1.53 +
    1.54 +      if (i->close && i->source == j->dest)
    1.55 +        i->close = false;
    1.56 +
    1.57 +      if (i->close && i->source == j->source) {
    1.58 +        i->close = false;
    1.59 +        j->close = true;
    1.60 +      }
    1.61 +    }
    1.62 +
    1.63 +    if (!is_identity) {
    1.64 +      if (!delegate->Move(i->source, i->dest))
    1.65 +        return false;
    1.66 +    }
    1.67 +
    1.68 +    if (!is_identity && i->close)
    1.69 +      delegate->Close(i->source);
    1.70 +  }
    1.71 +
    1.72 +  for (unsigned i = 0; i < next_extra_fd; i++)
    1.73 +    delegate->Close(extra_fds[i]);
    1.74 +
    1.75 +  return true;
    1.76 +}
    1.77 +
    1.78 +bool PerformInjectiveMultimap(const InjectiveMultimap& m_in,
    1.79 +                              InjectionDelegate* delegate) {
    1.80 +    InjectiveMultimap m(m_in);
    1.81 +    return PerformInjectiveMultimapDestructive(&m, delegate);
    1.82 +}
    1.83 +
    1.84 +bool FileDescriptorTableInjection::Duplicate(int* result, int fd) {
    1.85 +  *result = HANDLE_EINTR(dup(fd));
    1.86 +  return *result >= 0;
    1.87 +}
    1.88 +
    1.89 +bool FileDescriptorTableInjection::Move(int src, int dest) {
    1.90 +  return HANDLE_EINTR(dup2(src, dest)) != -1;
    1.91 +}
    1.92 +
    1.93 +void FileDescriptorTableInjection::Close(int fd) {
    1.94 +  HANDLE_EINTR(close(fd));
    1.95 +}
    1.96 +
    1.97 +}  // namespace base

mercurial