blob: 335b008acdb2c1ec725ef17a254a8747050503fb [file] [log] [blame]
[email protected]91d91fa2011-04-29 20:45:221// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]3f04f2b2009-04-30 19:40:032// 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_
[email protected]32b76ef2010-07-26 23:08:247#pragma once
[email protected]3f04f2b2009-04-30 19:40:038
9// This code exists to perform the shuffling of file descriptors which is
10// commonly needed when forking subprocesses. The naive approve is very simple,
11// just call dup2 to setup the desired descriptors, but wrong. It's tough to
12// handle the edge cases (like mapping 0 -> 1, 1 -> 0) correctly.
13//
14// In order to unittest this code, it's broken into the abstract action (an
15// injective multimap) and the concrete code for dealing with file descriptors.
16// Users should use the code like this:
17// base::InjectiveMultimap file_descriptor_map;
18// file_descriptor_map.push_back(base::InjectionArc(devnull, 0, true));
19// file_descriptor_map.push_back(base::InjectionArc(devnull, 2, true));
20// file_descriptor_map.push_back(base::InjectionArc(pipe[1], 1, true));
21// base::ShuffleFileDescriptors(file_descriptor_map);
22//
23// and trust the the Right Thing will get done.
24
25#include <vector>
26
[email protected]0bea7252011-08-05 15:34:0027#include "base/base_export.h"
[email protected]91d91fa2011-04-29 20:45:2228
[email protected]3f04f2b2009-04-30 19:40:0329namespace base {
30
31// A Delegate which performs the actions required to perform an injective
32// multimapping in place.
33class InjectionDelegate {
34 public:
35 // Duplicate |fd|, an element of the domain, and write a fresh element of the
36 // domain into |result|. Returns true iff successful.
37 virtual bool Duplicate(int* result, int fd) = 0;
38 // Destructively move |src| to |dest|, overwriting |dest|. Returns true iff
39 // successful.
40 virtual bool Move(int src, int dest) = 0;
41 // Delete an element of the domain.
42 virtual void Close(int fd) = 0;
[email protected]20cb5f482009-12-16 01:01:2543
44 protected:
45 virtual ~InjectionDelegate() {}
[email protected]3f04f2b2009-04-30 19:40:0346};
47
48// An implementation of the InjectionDelegate interface using the file
49// descriptor table of the current process as the domain.
50class FileDescriptorTableInjection : public InjectionDelegate {
[email protected]78994ab02010-12-08 18:06:4451 virtual bool Duplicate(int* result, int fd);
52 virtual bool Move(int src, int dest);
53 virtual void Close(int fd);
[email protected]3f04f2b2009-04-30 19:40:0354};
55
56// A single arc of the directed graph which describes an injective multimapping.
57struct InjectionArc {
58 InjectionArc(int in_source, int in_dest, bool in_close)
59 : source(in_source),
60 dest(in_dest),
61 close(in_close) {
62 }
63
64 int source;
65 int dest;
66 bool close; // if true, delete the source element after performing the
67 // mapping.
68};
69
70typedef std::vector<InjectionArc> InjectiveMultimap;
71
[email protected]0bea7252011-08-05 15:34:0072BASE_EXPORT bool PerformInjectiveMultimap(const InjectiveMultimap& map,
73 InjectionDelegate* delegate);
[email protected]3f04f2b2009-04-30 19:40:0374
[email protected]0bea7252011-08-05 15:34:0075BASE_EXPORT bool PerformInjectiveMultimapDestructive(
76 InjectiveMultimap* map,
77 InjectionDelegate* delegate);
[email protected]ef73044e2010-03-11 15:25:5478
79// This function will not call malloc but will mutate |map|
80static inline bool ShuffleFileDescriptors(InjectiveMultimap* map) {
[email protected]3f04f2b2009-04-30 19:40:0381 FileDescriptorTableInjection delegate;
[email protected]ef73044e2010-03-11 15:25:5482 return PerformInjectiveMultimapDestructive(map, &delegate);
[email protected]3f04f2b2009-04-30 19:40:0383}
84
85} // namespace base
86
[email protected]2fdc86a2010-01-26 23:08:0287#endif // BASE_FILE_DESCRIPTOR_SHUFFLE_H_