1+ use nix;
12use nix:: mount:: { mount, MsFlags } ;
23use nix:: sched:: { unshare, CloneFlags } ;
34use nix:: sys:: signal:: { kill, Signal } ;
45use nix:: sys:: wait:: { waitpid, WaitPidFlag , WaitStatus } ;
5- use nix:: unistd;
6- use nix:: unistd:: { fork, ForkResult } ;
6+ use nix:: unistd:: { self , fork, ForkResult } ;
77use std:: env;
88use std:: fs;
99use std:: io;
1010use std:: io:: prelude:: * ;
1111use std:: os:: unix:: fs:: symlink;
1212use std:: os:: unix:: process:: CommandExt ;
13- use std:: path:: Path ;
14- use std:: path:: PathBuf ;
13+ use std:: path:: { Path , PathBuf } ;
1514use std:: process;
1615use std:: string:: String ;
17- use tempfile:: TempDir ;
16+
17+ mod mkdtemp;
1818
1919const NONE : Option < & ' static [ u8 ] > = None ;
2020
@@ -48,8 +48,7 @@ impl<'a> RunChroot<'a> {
4848 let mountpoint = self . rootdir . join ( entry. file_name ( ) ) ;
4949 if let Err ( e) = fs:: create_dir ( & mountpoint) {
5050 if e. kind ( ) != io:: ErrorKind :: AlreadyExists {
51- let e2: io:: Result < ( ) > = Err ( e) ;
52- e2. unwrap_or_else ( |_| panic ! ( "failed to create {}" , & mountpoint. display( ) ) ) ;
51+ panic ! ( "failed to create {}: {}" , & mountpoint. display( ) , e) ;
5352 }
5453 }
5554
@@ -59,15 +58,15 @@ impl<'a> RunChroot<'a> {
5958 fn bind_mount_file ( & self , entry : & fs:: DirEntry ) {
6059 let mountpoint = self . rootdir . join ( entry. file_name ( ) ) ;
6160 fs:: File :: create ( & mountpoint)
62- . unwrap_or_else ( |_ | panic ! ( "failed to create {}" , & mountpoint. display( ) ) ) ;
61+ . unwrap_or_else ( |err | panic ! ( "failed to create {}: {} " , & mountpoint. display( ) , err ) ) ;
6362
6463 bind_mount ( & entry. path ( ) , & mountpoint)
6564 }
6665
6766 fn mirror_symlink ( & self , entry : & fs:: DirEntry ) {
6867 let path = entry. path ( ) ;
6968 let target = fs:: read_link ( & path)
70- . unwrap_or_else ( |_ | panic ! ( "failed to resolve symlink {}" , & path. display( ) ) ) ;
69+ . unwrap_or_else ( |err | panic ! ( "failed to resolve symlink {}: {} " , & path. display( ) , err ) ) ;
7170 let link_path = self . rootdir . join ( entry. file_name ( ) ) ;
7271 symlink ( & target, & link_path) . unwrap_or_else ( |_| {
7372 panic ! (
@@ -87,7 +86,7 @@ impl<'a> RunChroot<'a> {
8786 let path = entry. path ( ) ;
8887 let stat = entry
8988 . metadata ( )
90- . unwrap_or_else ( |_ | panic ! ( "cannot get stat of {}" , path. display( ) ) ) ;
89+ . unwrap_or_else ( |err | panic ! ( "cannot get stat of {}: {} " , path. display( ) , err ) ) ;
9190 if stat. is_dir ( ) {
9291 self . bind_mount_directory ( & entry) ;
9392 } else if stat. is_file ( ) {
@@ -115,19 +114,19 @@ impl<'a> RunChroot<'a> {
115114 // mount the store
116115 let nix_mount = self . rootdir . join ( "nix" ) ;
117116 fs:: create_dir ( & nix_mount)
118- . unwrap_or_else ( |_ | panic ! ( "failed to create {}" , & nix_mount. display( ) ) ) ;
117+ . unwrap_or_else ( |err | panic ! ( "failed to create {}: {} " , & nix_mount. display( ) , err ) ) ;
119118 mount (
120119 Some ( nixdir) ,
121120 & nix_mount,
122121 Some ( "none" ) ,
123122 MsFlags :: MS_BIND | MsFlags :: MS_REC ,
124123 NONE ,
125124 )
126- . unwrap_or_else ( |_ | panic ! ( "failed to bind mount {} to /nix" , nixdir. display( ) ) ) ;
125+ . unwrap_or_else ( |err | panic ! ( "failed to bind mount {} to /nix: {} " , nixdir. display( ) , err ) ) ;
127126
128127 // chroot
129128 unistd:: chroot ( self . rootdir )
130- . unwrap_or_else ( |_ | panic ! ( "chroot({})" , self . rootdir. display( ) , ) ) ;
129+ . unwrap_or_else ( |err | panic ! ( "chroot({}): {} " , self . rootdir. display( ) , err ) ) ;
131130
132131 env:: set_current_dir ( "/" ) . expect ( "cannot change directory to /" ) ;
133132
@@ -163,48 +162,38 @@ impl<'a> RunChroot<'a> {
163162 }
164163}
165164
166- fn wait_for_child ( child_pid : unistd:: Pid , tempdir : TempDir , rootdir : & Path ) {
165+ fn wait_for_child ( rootdir : & Path , child_pid : unistd:: Pid ) -> ! {
166+ let mut exit_status = 1 ;
167167 loop {
168168 match waitpid ( child_pid, Some ( WaitPidFlag :: WUNTRACED ) ) {
169169 Ok ( WaitStatus :: Signaled ( child, Signal :: SIGSTOP , _) ) => {
170170 let _ = kill ( unistd:: getpid ( ) , Signal :: SIGSTOP ) ;
171171 let _ = kill ( child, Signal :: SIGCONT ) ;
172172 }
173173 Ok ( WaitStatus :: Signaled ( _, signal, _) ) => {
174- kill ( unistd:: getpid ( ) , signal)
175- . unwrap_or_else ( |_| panic ! ( "failed to send {} signal to our self" , signal) ) ;
174+ kill ( unistd:: getpid ( ) , signal) . unwrap_or_else ( |err| {
175+ panic ! ( "failed to send {} signal to our self: {}" , signal, err)
176+ } ) ;
176177 }
177178 Ok ( WaitStatus :: Exited ( _, status) ) => {
178- tempdir. close ( ) . unwrap_or_else ( |_| {
179- panic ! (
180- "failed to remove temporary directory: {}" ,
181- rootdir. display( )
182- )
183- } ) ;
184- process:: exit ( status) ;
179+ exit_status = status;
180+ break ;
185181 }
186182 Ok ( what) => {
187- tempdir. close ( ) . unwrap_or_else ( |_| {
188- panic ! (
189- "failed to remove temporary directory: {}" ,
190- rootdir. display( )
191- )
192- } ) ;
193183 eprintln ! ( "unexpected wait event happend: {:?}" , what) ;
194- process :: exit ( 1 ) ;
184+ break ;
195185 }
196186 Err ( e) => {
197- tempdir. close ( ) . unwrap_or_else ( |_| {
198- panic ! (
199- "failed to remove temporary directory: {}" ,
200- rootdir. display( )
201- )
202- } ) ;
203187 eprintln ! ( "waitpid failed: {}" , e) ;
204- process :: exit ( 1 ) ;
188+ break ;
205189 }
206190 } ;
207191 }
192+
193+ fs:: remove_dir_all ( rootdir)
194+ . unwrap_or_else ( |err| panic ! ( "cannot remove tempdir {}: {}" , rootdir. display( ) , err) ) ;
195+
196+ process:: exit ( exit_status) ;
208197}
209198
210199fn main ( ) {
@@ -213,14 +202,15 @@ fn main() {
213202 eprintln ! ( "Usage: {} <nixpath> <command>\n " , args[ 0 ] ) ;
214203 process:: exit ( 1 ) ;
215204 }
216- let tempdir = TempDir :: new ( ) . expect ( "failed to create temporary directory for mount point" ) ;
217- let rootdir = PathBuf :: from ( tempdir. path ( ) ) ;
205+
206+ let rootdir = mkdtemp:: mkdtemp ( "nix-chroot.XXXXXX" )
207+ . unwrap_or_else ( |err| panic ! ( "failed to create temporary directory: {}" , err) ) ;
218208
219209 let nixdir = fs:: canonicalize ( & args[ 1 ] )
220- . unwrap_or_else ( |_ | panic ! ( "failed to resolve nix directory {}" , & args[ 1 ] ) ) ;
210+ . unwrap_or_else ( |err | panic ! ( "failed to resolve nix directory {}: {} " , & args[ 1 ] , err ) ) ;
221211
222212 match unsafe { fork ( ) } {
223- Ok ( ForkResult :: Parent { child, .. } ) => wait_for_child ( child , tempdir , & rootdir) ,
213+ Ok ( ForkResult :: Parent { child, .. } ) => wait_for_child ( & rootdir, child ) ,
224214 Ok ( ForkResult :: Child ) => RunChroot :: new ( & rootdir) . run_chroot ( & nixdir, & args[ 2 ] , & args[ 3 ..] ) ,
225215 Err ( e) => {
226216 eprintln ! ( "fork failed: {}" , e) ;
0 commit comments