1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/file_descriptor_shuffle.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,79 @@ 1.4 +// Copyright (c) 2009 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#ifndef BASE_FILE_DESCRIPTOR_SHUFFLE_H_ 1.9 +#define BASE_FILE_DESCRIPTOR_SHUFFLE_H_ 1.10 + 1.11 +// This code exists to perform the shuffling of file descriptors which is 1.12 +// commonly needed when forking subprocesses. The naive approve is very simple, 1.13 +// just call dup2 to setup the desired descriptors, but wrong. It's tough to 1.14 +// handle the edge cases (like mapping 0 -> 1, 1 -> 0) correctly. 1.15 +// 1.16 +// In order to unittest this code, it's broken into the abstract action (an 1.17 +// injective multimap) and the concrete code for dealing with file descriptors. 1.18 +// Users should use the code like this: 1.19 +// base::InjectiveMultimap file_descriptor_map; 1.20 +// file_descriptor_map.push_back(base::InjectionArc(devnull, 0, true)); 1.21 +// file_descriptor_map.push_back(base::InjectionArc(devnull, 2, true)); 1.22 +// file_descriptor_map.push_back(base::InjectionArc(pipe[1], 1, true)); 1.23 +// base::ShuffleFileDescriptors(file_descriptor_map); 1.24 +// 1.25 +// and trust the the Right Thing will get done. 1.26 + 1.27 +#include <vector> 1.28 + 1.29 +namespace base { 1.30 + 1.31 +// A Delegate which performs the actions required to perform an injective 1.32 +// multimapping in place. 1.33 +class InjectionDelegate { 1.34 + public: 1.35 + // Duplicate |fd|, an element of the domain, and write a fresh element of the 1.36 + // domain into |result|. Returns true iff successful. 1.37 + virtual bool Duplicate(int* result, int fd) = 0; 1.38 + // Destructively move |src| to |dest|, overwriting |dest|. Returns true iff 1.39 + // successful. 1.40 + virtual bool Move(int src, int dest) = 0; 1.41 + // Delete an element of the domain. 1.42 + virtual void Close(int fd) = 0; 1.43 +}; 1.44 + 1.45 +// An implementation of the InjectionDelegate interface using the file 1.46 +// descriptor table of the current process as the domain. 1.47 +class FileDescriptorTableInjection : public InjectionDelegate { 1.48 + bool Duplicate(int* result, int fd); 1.49 + bool Move(int src, int dest); 1.50 + void Close(int fd); 1.51 +}; 1.52 + 1.53 +// A single arc of the directed graph which describes an injective multimapping. 1.54 +struct InjectionArc { 1.55 + InjectionArc(int in_source, int in_dest, bool in_close) 1.56 + : source(in_source), 1.57 + dest(in_dest), 1.58 + close(in_close) { 1.59 + } 1.60 + 1.61 + int source; 1.62 + int dest; 1.63 + bool close; // if true, delete the source element after performing the 1.64 + // mapping. 1.65 +}; 1.66 + 1.67 +typedef std::vector<InjectionArc> InjectiveMultimap; 1.68 + 1.69 +bool PerformInjectiveMultimap(const InjectiveMultimap& map, 1.70 + InjectionDelegate* delegate); 1.71 +bool PerformInjectiveMultimapDestructive(InjectiveMultimap* map, 1.72 + InjectionDelegate* delegate); 1.73 + 1.74 +// This function will not call malloc but will mutate |map| 1.75 +static inline bool ShuffleFileDescriptors(InjectiveMultimap *map) { 1.76 + FileDescriptorTableInjection delegate; 1.77 + return PerformInjectiveMultimapDestructive(map, &delegate); 1.78 +} 1.79 + 1.80 +} // namespace base 1.81 + 1.82 +#endif // !BASE_FILE_DESCRIPTOR_SHUFFLE_H_