1313 See the License for the specific language governing permissions and
1414 limitations under the License.
1515*/
16- #[ cfg( not( feature = "async" ) ) ]
17- use std:: io:: { Read , Write } ;
16+
1817use std:: {
1918 fmt:: Debug ,
2019 fs:: { File , OpenOptions } ,
2120 io:: Result ,
22- os:: unix:: {
23- fs:: OpenOptionsExt ,
24- io:: { AsRawFd , OwnedFd } ,
25- } ,
21+ os:: unix:: { fs:: OpenOptionsExt , io:: AsRawFd } ,
2622 process:: Stdio ,
2723 sync:: Mutex ,
2824} ;
2925
30- use log:: debug;
3126use nix:: unistd:: { Gid , Uid } ;
32- #[ cfg( feature = "async" ) ]
33- use tokio:: io:: { AsyncRead , AsyncWrite } ;
34- use tokio:: net:: unix:: pipe;
35-
36- use crate :: Command ;
37-
38- pub trait Io : Debug + Send + Sync {
39- /// Return write side of stdin
40- #[ cfg( not( feature = "async" ) ) ]
41- fn stdin ( & self ) -> Option < Box < dyn Write + Send + Sync > > {
42- None
43- }
44-
45- /// Return read side of stdout
46- #[ cfg( not( feature = "async" ) ) ]
47- fn stdout ( & self ) -> Option < Box < dyn Read + Send > > {
48- None
49- }
50-
51- /// Return read side of stderr
52- #[ cfg( not( feature = "async" ) ) ]
53- fn stderr ( & self ) -> Option < Box < dyn Read + Send > > {
54- None
55- }
56-
57- /// Return write side of stdin
58- #[ cfg( feature = "async" ) ]
59- fn stdin ( & self ) -> Option < Box < dyn AsyncWrite + Send + Sync + Unpin > > {
60- None
61- }
62-
63- /// Return read side of stdout
64- #[ cfg( feature = "async" ) ]
65- fn stdout ( & self ) -> Option < Box < dyn AsyncRead + Send + Sync + Unpin > > {
66- None
67- }
68-
69- /// Return read side of stderr
70- #[ cfg( feature = "async" ) ]
71- fn stderr ( & self ) -> Option < Box < dyn AsyncRead + Send + Sync + Unpin > > {
72- None
73- }
7427
75- /// Set IO for passed command.
76- /// Read side of stdin, write side of stdout and write side of stderr should be provided to command.
77- fn set ( & self , cmd : & mut Command ) -> Result < ( ) > ;
78-
79- /// Only close write side (should be stdout/err "from" runc process)
80- fn close_after_start ( & self ) ;
81- }
28+ use crate :: { Command , Io , Pipe , PipedIo } ;
8229
8330#[ derive( Debug , Clone ) ]
8431pub struct IOOption {
@@ -97,32 +44,6 @@ impl Default for IOOption {
9744 }
9845}
9946
100- /// Struct to represent a pipe that can be used to transfer stdio inputs and outputs.
101- ///
102- /// With this Io driver, methods of [crate::Runc] may capture the output/error messages.
103- /// When one side of the pipe is closed, the state will be represented with [`None`].
104- #[ derive( Debug ) ]
105- pub struct Pipe {
106- rd : OwnedFd ,
107- wr : OwnedFd ,
108- }
109-
110- #[ derive( Debug ) ]
111- pub struct PipedIo {
112- stdin : Option < Pipe > ,
113- stdout : Option < Pipe > ,
114- stderr : Option < Pipe > ,
115- }
116-
117- impl Pipe {
118- fn new ( ) -> std:: io:: Result < Self > {
119- let ( tx, rx) = pipe:: pipe ( ) ?;
120- let rd = tx. into_blocking_fd ( ) ?;
121- let wr = rx. into_blocking_fd ( ) ?;
122- Ok ( Self { rd, wr } )
123- }
124- }
125-
12647impl PipedIo {
12748 pub fn new ( uid : u32 , gid : u32 , opts : & IOOption ) -> std:: io:: Result < Self > {
12849 Ok ( Self {
@@ -156,99 +77,6 @@ impl PipedIo {
15677 }
15778}
15879
159- impl Io for PipedIo {
160- #[ cfg( not( feature = "async" ) ) ]
161- fn stdin ( & self ) -> Option < Box < dyn Write + Send + Sync > > {
162- self . stdin . as_ref ( ) . and_then ( |pipe| {
163- pipe. wr
164- . try_clone ( )
165- . map ( |x| Box :: new ( x) as Box < dyn Write + Send + Sync > )
166- . ok ( )
167- } )
168- }
169-
170- #[ cfg( feature = "async" ) ]
171- fn stdin ( & self ) -> Option < Box < dyn AsyncWrite + Send + Sync + Unpin > > {
172- self . stdin . as_ref ( ) . and_then ( |pipe| {
173- let fd = pipe. wr . as_raw_fd ( ) ;
174- tokio_pipe:: PipeWrite :: from_raw_fd_checked ( fd)
175- . map ( |x| Box :: new ( x) as Box < dyn AsyncWrite + Send + Sync + Unpin > )
176- . ok ( )
177- } )
178- }
179-
180- #[ cfg( not( feature = "async" ) ) ]
181- fn stdout ( & self ) -> Option < Box < dyn Read + Send > > {
182- self . stdout . as_ref ( ) . and_then ( |pipe| {
183- pipe. rd
184- . try_clone ( )
185- . map ( |x| Box :: new ( x) as Box < dyn Read + Send > )
186- . ok ( )
187- } )
188- }
189-
190- #[ cfg( feature = "async" ) ]
191- fn stdout ( & self ) -> Option < Box < dyn AsyncRead + Send + Sync + Unpin > > {
192- self . stdout . as_ref ( ) . and_then ( |pipe| {
193- let fd = pipe. rd . as_raw_fd ( ) ;
194- tokio_pipe:: PipeRead :: from_raw_fd_checked ( fd)
195- . map ( |x| Box :: new ( x) as Box < dyn AsyncRead + Send + Sync + Unpin > )
196- . ok ( )
197- } )
198- }
199-
200- #[ cfg( not( feature = "async" ) ) ]
201- fn stderr ( & self ) -> Option < Box < dyn Read + Send > > {
202- self . stderr . as_ref ( ) . and_then ( |pipe| {
203- pipe. rd
204- . try_clone ( )
205- . map ( |x| Box :: new ( x) as Box < dyn Read + Send > )
206- . ok ( )
207- } )
208- }
209-
210- #[ cfg( feature = "async" ) ]
211- fn stderr ( & self ) -> Option < Box < dyn AsyncRead + Send + Sync + Unpin > > {
212- self . stderr . as_ref ( ) . and_then ( |pipe| {
213- let fd = pipe. rd . as_raw_fd ( ) ;
214- tokio_pipe:: PipeRead :: from_raw_fd_checked ( fd)
215- . map ( |x| Box :: new ( x) as Box < dyn AsyncRead + Send + Sync + Unpin > )
216- . ok ( )
217- } )
218- }
219-
220- // Note that this internally use [`std::fs::File`]'s `try_clone()`.
221- // Thus, the files passed to commands will be not closed after command exit.
222- fn set ( & self , cmd : & mut Command ) -> std:: io:: Result < ( ) > {
223- if let Some ( p) = self . stdin . as_ref ( ) {
224- let pr = p. rd . try_clone ( ) ?;
225- cmd. stdin ( pr) ;
226- }
227-
228- if let Some ( p) = self . stdout . as_ref ( ) {
229- let pw = p. wr . try_clone ( ) ?;
230- cmd. stdout ( pw) ;
231- }
232-
233- if let Some ( p) = self . stderr . as_ref ( ) {
234- let pw = p. wr . try_clone ( ) ?;
235- cmd. stdout ( pw) ;
236- }
237-
238- Ok ( ( ) )
239- }
240-
241- fn close_after_start ( & self ) {
242- if let Some ( p) = self . stdout . as_ref ( ) {
243- nix:: unistd:: close ( p. wr . as_raw_fd ( ) ) . unwrap_or_else ( |e| debug ! ( "close stdout: {}" , e) ) ;
244- }
245-
246- if let Some ( p) = self . stderr . as_ref ( ) {
247- nix:: unistd:: close ( p. wr . as_raw_fd ( ) ) . unwrap_or_else ( |e| debug ! ( "close stderr: {}" , e) ) ;
248- }
249- }
250- }
251-
25280/// IO driver to direct output/error messages to /dev/null.
25381///
25482/// With this Io driver, all methods of [crate::Runc] can't capture the output/error messages.
0 commit comments