Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/file_descriptor_shuffle.h"
      6 
      7 #include <errno.h>
      8 #include <unistd.h>
      9 
     10 #include "base/eintr_wrapper.h"
     11 #include "base/logging.h"
     12 
     13 namespace base {
     14 
     15 bool PerformInjectiveMultimap(const InjectiveMultimap& m_in,
     16                               InjectionDelegate* delegate) {
     17   InjectiveMultimap m(m_in);
     18   std::vector<int> extra_fds;
     19 
     20   for (InjectiveMultimap::iterator i = m.begin(); i != m.end(); ++i) {
     21     int temp_fd = -1;
     22 
     23     // We DCHECK the injectiveness of the mapping.
     24     for (InjectiveMultimap::iterator j = i + 1; j != m.end(); ++j) {
     25       DCHECK(i->dest != j->dest) << "Both fd " << i->source
     26           << " and " << j->source << " map to " << i->dest;
     27     }
     28 
     29     const bool is_identity = i->source == i->dest;
     30 
     31     for (InjectiveMultimap::iterator j = i + 1; j != m.end(); ++j) {
     32       if (!is_identity && i->dest == j->source) {
     33         if (temp_fd == -1) {
     34           if (!delegate->Duplicate(&temp_fd, i->dest))
     35             return false;
     36           extra_fds.push_back(temp_fd);
     37         }
     38 
     39         j->source = temp_fd;
     40         j->close = false;
     41       }
     42 
     43       if (i->close && i->source == j->dest)
     44         i->close = false;
     45 
     46       if (i->close && i->source == j->source) {
     47         i->close = false;
     48         j->close = true;
     49       }
     50     }
     51 
     52     if (!is_identity) {
     53       if (!delegate->Move(i->source, i->dest))
     54         return false;
     55     }
     56 
     57     if (!is_identity && i->close)
     58       delegate->Close(i->source);
     59   }
     60 
     61   for (std::vector<int>::const_iterator
     62        i = extra_fds.begin(); i != extra_fds.end(); ++i) {
     63     delegate->Close(*i);
     64   }
     65 
     66   return true;
     67 }
     68 
     69 bool FileDescriptorTableInjection::Duplicate(int* result, int fd) {
     70   *result = HANDLE_EINTR(dup(fd));
     71   return *result >= 0;
     72 }
     73 
     74 bool FileDescriptorTableInjection::Move(int src, int dest) {
     75   return HANDLE_EINTR(dup2(src, dest)) != -1;
     76 }
     77 
     78 void FileDescriptorTableInjection::Close(int fd) {
     79   int ret = HANDLE_EINTR(close(fd));
     80   DPCHECK(ret == 0);
     81 }
     82 
     83 }  // namespace base
     84