Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / containerd / go-runc / io.go
1 package runc
2
3 import (
4         "io"
5         "os"
6         "os/exec"
7
8         "golang.org/x/sys/unix"
9 )
10
11 type IO interface {
12         io.Closer
13         Stdin() io.WriteCloser
14         Stdout() io.ReadCloser
15         Stderr() io.ReadCloser
16         Set(*exec.Cmd)
17 }
18
19 type StartCloser interface {
20         CloseAfterStart() error
21 }
22
23 // NewPipeIO creates pipe pairs to be used with runc
24 func NewPipeIO(uid, gid int) (i IO, err error) {
25         var pipes []*pipe
26         // cleanup in case of an error
27         defer func() {
28                 if err != nil {
29                         for _, p := range pipes {
30                                 p.Close()
31                         }
32                 }
33         }()
34         stdin, err := newPipe(uid, gid)
35         if err != nil {
36                 return nil, err
37         }
38         pipes = append(pipes, stdin)
39
40         stdout, err := newPipe(uid, gid)
41         if err != nil {
42                 return nil, err
43         }
44         pipes = append(pipes, stdout)
45
46         stderr, err := newPipe(uid, gid)
47         if err != nil {
48                 return nil, err
49         }
50         pipes = append(pipes, stderr)
51
52         return &pipeIO{
53                 in:  stdin,
54                 out: stdout,
55                 err: stderr,
56         }, nil
57 }
58
59 func newPipe(uid, gid int) (*pipe, error) {
60         r, w, err := os.Pipe()
61         if err != nil {
62                 return nil, err
63         }
64         if err := unix.Fchown(int(r.Fd()), uid, gid); err != nil {
65                 return nil, err
66         }
67         if err := unix.Fchown(int(w.Fd()), uid, gid); err != nil {
68                 return nil, err
69         }
70         return &pipe{
71                 r: r,
72                 w: w,
73         }, nil
74 }
75
76 type pipe struct {
77         r *os.File
78         w *os.File
79 }
80
81 func (p *pipe) Close() error {
82         err := p.r.Close()
83         if werr := p.w.Close(); err == nil {
84                 err = werr
85         }
86         return err
87 }
88
89 type pipeIO struct {
90         in  *pipe
91         out *pipe
92         err *pipe
93 }
94
95 func (i *pipeIO) Stdin() io.WriteCloser {
96         return i.in.w
97 }
98
99 func (i *pipeIO) Stdout() io.ReadCloser {
100         return i.out.r
101 }
102
103 func (i *pipeIO) Stderr() io.ReadCloser {
104         return i.err.r
105 }
106
107 func (i *pipeIO) Close() error {
108         var err error
109         for _, v := range []*pipe{
110                 i.in,
111                 i.out,
112                 i.err,
113         } {
114                 if cerr := v.Close(); err == nil {
115                         err = cerr
116                 }
117         }
118         return err
119 }
120
121 func (i *pipeIO) CloseAfterStart() error {
122         for _, f := range []*os.File{
123                 i.out.w,
124                 i.err.w,
125         } {
126                 f.Close()
127         }
128         return nil
129 }
130
131 // Set sets the io to the exec.Cmd
132 func (i *pipeIO) Set(cmd *exec.Cmd) {
133         cmd.Stdin = i.in.r
134         cmd.Stdout = i.out.w
135         cmd.Stderr = i.err.w
136 }
137
138 func NewSTDIO() (IO, error) {
139         return &stdio{}, nil
140 }
141
142 type stdio struct {
143 }
144
145 func (s *stdio) Close() error {
146         return nil
147 }
148
149 func (s *stdio) Set(cmd *exec.Cmd) {
150         cmd.Stdin = os.Stdin
151         cmd.Stdout = os.Stdout
152         cmd.Stderr = os.Stderr
153 }
154
155 func (s *stdio) Stdin() io.WriteCloser {
156         return os.Stdin
157 }
158
159 func (s *stdio) Stdout() io.ReadCloser {
160         return os.Stdout
161 }
162
163 func (s *stdio) Stderr() io.ReadCloser {
164         return os.Stderr
165 }