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.
5 #include "base/file_descriptor_shuffle.h"
10 #include "base/eintr_wrapper.h"
11 #include "base/logging.h"
15 bool PerformInjectiveMultimapDestructive(
16 InjectiveMultimap
* m
, InjectionDelegate
* delegate
) {
17 static const size_t kMaxExtraFDs
= 16;
18 int extra_fds
[kMaxExtraFDs
];
19 unsigned next_extra_fd
= 0;
21 // DANGER: this function may not allocate.
23 for (InjectiveMultimap::iterator i
= m
->begin(); i
!= m
->end(); ++i
) {
26 // We DCHECK the injectiveness of the mapping.
27 for (InjectiveMultimap::iterator j
= i
+ 1; j
!= m
->end(); ++j
) {
28 DCHECK(i
->dest
!= j
->dest
) << "Both fd " << i
->source
29 << " and " << j
->source
<< " map to " << i
->dest
;
32 const bool is_identity
= i
->source
== i
->dest
;
34 for (InjectiveMultimap::iterator j
= i
+ 1; j
!= m
->end(); ++j
) {
35 if (!is_identity
&& i
->dest
== j
->source
) {
37 if (!delegate
->Duplicate(&temp_fd
, i
->dest
))
39 if (next_extra_fd
< kMaxExtraFDs
) {
40 extra_fds
[next_extra_fd
++] = temp_fd
;
42 RAW_LOG(ERROR
, "PerformInjectiveMultimapDestructive overflowed "
43 "extra_fds. Leaking file descriptors!");
51 if (i
->close
&& i
->source
== j
->dest
)
54 if (i
->close
&& i
->source
== j
->source
) {
61 if (!delegate
->Move(i
->source
, i
->dest
))
65 if (!is_identity
&& i
->close
)
66 delegate
->Close(i
->source
);
69 for (unsigned i
= 0; i
< next_extra_fd
; i
++)
70 delegate
->Close(extra_fds
[i
]);
75 bool PerformInjectiveMultimap(const InjectiveMultimap
& m_in
,
76 InjectionDelegate
* delegate
) {
77 InjectiveMultimap
m(m_in
);
78 return PerformInjectiveMultimapDestructive(&m
, delegate
);
81 bool FileDescriptorTableInjection::Duplicate(int* result
, int fd
) {
82 *result
= HANDLE_EINTR(dup(fd
));
86 bool FileDescriptorTableInjection::Move(int src
, int dest
) {
87 return HANDLE_EINTR(dup2(src
, dest
)) != -1;
90 void FileDescriptorTableInjection::Close(int fd
) {
91 int ret
= HANDLE_EINTR(close(fd
));