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 PerformInjectiveMultimap(const InjectiveMultimap & m_in,InjectionDelegate * delegate)15bool 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 Duplicate(int * result,int fd)69bool FileDescriptorTableInjection::Duplicate(int* result, int fd) { 70 *result = HANDLE_EINTR(dup(fd)); 71 return *result >= 0; 72 } 73 Move(int src,int dest)74bool FileDescriptorTableInjection::Move(int src, int dest) { 75 return HANDLE_EINTR(dup2(src, dest)) != -1; 76 } 77 Close(int fd)78void FileDescriptorTableInjection::Close(int fd) { 79 int ret = HANDLE_EINTR(close(fd)); 80 DPCHECK(ret == 0); 81 } 82 83 } // namespace base 84