OLD | NEW |
(Empty) | |
| 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 #ifndef BASE_FILE_DESCRIPTOR_SHUFFLE_H_ |
| 6 #define BASE_FILE_DESCRIPTOR_SHUFFLE_H_ |
| 7 |
| 8 // This code exists to perform the shuffling of file descriptors which is |
| 9 // commonly needed when forking subprocesses. The naive approve is very simple, |
| 10 // just call dup2 to setup the desired descriptors, but wrong. It's tough to |
| 11 // handle the edge cases (like mapping 0 -> 1, 1 -> 0) correctly. |
| 12 // |
| 13 // In order to unittest this code, it's broken into the abstract action (an |
| 14 // injective multimap) and the concrete code for dealing with file descriptors. |
| 15 // Users should use the code like this: |
| 16 // base::InjectiveMultimap file_descriptor_map; |
| 17 // file_descriptor_map.push_back(base::InjectionArc(devnull, 0, true)); |
| 18 // file_descriptor_map.push_back(base::InjectionArc(devnull, 2, true)); |
| 19 // file_descriptor_map.push_back(base::InjectionArc(pipe[1], 1, true)); |
| 20 // base::ShuffleFileDescriptors(file_descriptor_map); |
| 21 // |
| 22 // and trust the the Right Thing will get done. |
| 23 |
| 24 #include <vector> |
| 25 |
| 26 namespace base { |
| 27 |
| 28 // A Delegate which performs the actions required to perform an injective |
| 29 // multimapping in place. |
| 30 class InjectionDelegate { |
| 31 public: |
| 32 // Duplicate |fd|, an element of the domain, and write a fresh element of the |
| 33 // domain into |result|. Returns true iff successful. |
| 34 virtual bool Duplicate(int* result, int fd) = 0; |
| 35 // Destructively move |src| to |dest|, overwriting |dest|. Returns true iff |
| 36 // successful. |
| 37 virtual bool Move(int src, int dest) = 0; |
| 38 // Delete an element of the domain. |
| 39 virtual void Close(int fd) = 0; |
| 40 }; |
| 41 |
| 42 // An implementation of the InjectionDelegate interface using the file |
| 43 // descriptor table of the current process as the domain. |
| 44 class FileDescriptorTableInjection : public InjectionDelegate { |
| 45 bool Duplicate(int* result, int fd); |
| 46 bool Move(int src, int dest); |
| 47 void Close(int fd); |
| 48 }; |
| 49 |
| 50 // A single arc of the directed graph which describes an injective multimapping. |
| 51 struct InjectionArc { |
| 52 InjectionArc(int in_source, int in_dest, bool in_close) |
| 53 : source(in_source), |
| 54 dest(in_dest), |
| 55 close(in_close) { |
| 56 } |
| 57 |
| 58 int source; |
| 59 int dest; |
| 60 bool close; // if true, delete the source element after performing the |
| 61 // mapping. |
| 62 }; |
| 63 |
| 64 typedef std::vector<InjectionArc> InjectiveMultimap; |
| 65 |
| 66 bool PerformInjectiveMultimap(const InjectiveMultimap& map, |
| 67 InjectionDelegate* delegate); |
| 68 |
| 69 static inline bool ShuffleFileDescriptors(const InjectiveMultimap& map) { |
| 70 FileDescriptorTableInjection delegate; |
| 71 return PerformInjectiveMultimap(map, &delegate); |
| 72 } |
| 73 |
| 74 } // namespace base |
| 75 |
| 76 #endif // !BASE_FILE_DESCRIPTOR_SHUFFLE_H_ |
OLD | NEW |