[email protected] | 3f04f2b | 2009-04-30 19:40:03 | [diff] [blame] | 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 | |||||
[email protected] | 157c61b | 2009-05-01 21:37:31 | [diff] [blame] | 10 | #include "base/eintr_wrapper.h" |
[email protected] | 3f04f2b | 2009-04-30 19:40:03 | [diff] [blame] | 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. | ||||
[email protected] | 4883a4e | 2009-06-06 19:59:36 | [diff] [blame] | 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 | } | ||||
[email protected] | 3f04f2b | 2009-04-30 19:40:03 | [diff] [blame] | 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) { | ||||
[email protected] | 157c61b | 2009-05-01 21:37:31 | [diff] [blame] | 70 | *result = HANDLE_EINTR(dup(fd)); |
[email protected] | 3f04f2b | 2009-04-30 19:40:03 | [diff] [blame] | 71 | return *result >= 0; |
72 | } | ||||
73 | |||||
74 | bool FileDescriptorTableInjection::Move(int src, int dest) { | ||||
[email protected] | 157c61b | 2009-05-01 21:37:31 | [diff] [blame] | 75 | return HANDLE_EINTR(dup2(src, dest)) != -1; |
[email protected] | 3f04f2b | 2009-04-30 19:40:03 | [diff] [blame] | 76 | } |
77 | |||||
78 | void FileDescriptorTableInjection::Close(int fd) { | ||||
[email protected] | 157c61b | 2009-05-01 21:37:31 | [diff] [blame] | 79 | HANDLE_EINTR(close(fd)); |
[email protected] | 3f04f2b | 2009-04-30 19:40:03 | [diff] [blame] | 80 | } |
81 | |||||
82 | } // namespace base |