11use crate :: context:: Context ;
2+ use crate :: tracer:: tracee_memory;
3+ use crate :: utils:: short_temp_files:: ShortTempFile ;
24use crate :: { ExitCode , R } ;
35use bincode:: { deserialize, serialize} ;
6+ use libc:: user_regs_struct;
7+ use nix:: unistd:: Pid ;
48use std:: fs;
59use std:: io:: Write ;
610use std:: os:: unix:: ffi:: OsStrExt ;
7- use std:: path:: Path ;
11+ use std:: path:: { Path , PathBuf } ;
812
913#[ derive( Debug , Serialize , Deserialize ) ]
1014pub struct Config {
1115 pub stdout : Vec < u8 > ,
1216 pub exitcode : i32 ,
1317}
1418
15- pub fn create_mock_executable ( context : & Context , config : Config ) -> R < Vec < u8 > > {
16- let mut result = b"#!" . to_vec ( ) ;
17- result. append (
18- & mut context
19- . scriptkeeper_executable ( )
20- . as_os_str ( )
21- . as_bytes ( )
22- . to_vec ( ) ,
23- ) ;
24- result. append ( & mut b" --executable-mock\n " . to_vec ( ) ) ;
25- result. append ( & mut serialize ( & config) ?) ;
26- Ok ( result)
19+ #[ derive( Debug ) ]
20+ pub struct ExecutableMock {
21+ temp_file : ShortTempFile ,
2722}
2823
29- pub fn run ( context : & Context , executable_mock_path : & Path ) -> R < ExitCode > {
30- let config: Config = deserialize ( & skip_hashbang_line ( fs:: read ( executable_mock_path) ?) ) ?;
31- context. stdout ( ) . write_all ( & config. stdout ) ?;
32- Ok ( ExitCode ( config. exitcode ) )
33- }
24+ impl ExecutableMock {
25+ pub fn new ( context : & Context , mock_config : Config ) -> R < ExecutableMock > {
26+ let mut contents = b"#!" . to_vec ( ) ;
27+ contents. append (
28+ & mut context
29+ . scriptkeeper_executable ( )
30+ . as_os_str ( )
31+ . as_bytes ( )
32+ . to_vec ( ) ,
33+ ) ;
34+ contents. append ( & mut b" --executable-mock\n " . to_vec ( ) ) ;
35+ contents. append ( & mut serialize ( & mock_config) ?) ;
36+ let temp_file = ShortTempFile :: new ( & contents) ?;
37+ Ok ( ExecutableMock { temp_file } )
38+ }
3439
35- fn skip_hashbang_line ( input : Vec < u8 > ) -> Vec < u8 > {
36- input
37- . clone ( )
38- . into_iter ( )
39- . skip_while ( |char : & u8 | * char != b'\n' )
40- . skip ( 1 )
41- . collect ( )
40+ pub fn path ( & self ) -> PathBuf {
41+ self . temp_file . path ( )
42+ }
43+
44+ pub fn poke_for_execve_syscall (
45+ pid : Pid ,
46+ registers : & user_regs_struct ,
47+ executable_mock_path : PathBuf ,
48+ ) -> R < ( ) > {
49+ tracee_memory:: poke_single_word_string (
50+ pid,
51+ registers. rdi ,
52+ & executable_mock_path. as_os_str ( ) . as_bytes ( ) ,
53+ )
54+ }
55+
56+ pub fn run ( context : & Context , executable_mock_path : & Path ) -> R < ExitCode > {
57+ let config: Config = deserialize ( & ExecutableMock :: skip_hashbang_line ( fs:: read (
58+ executable_mock_path,
59+ ) ?) ) ?;
60+ context. stdout ( ) . write_all ( & config. stdout ) ?;
61+ Ok ( ExitCode ( config. exitcode ) )
62+ }
63+
64+ fn skip_hashbang_line ( input : Vec < u8 > ) -> Vec < u8 > {
65+ input
66+ . clone ( )
67+ . into_iter ( )
68+ . skip_while ( |char : & u8 | * char != b'\n' )
69+ . skip ( 1 )
70+ . collect ( )
71+ }
4272}
4373
4474#[ cfg( test) ]
@@ -48,28 +78,28 @@ mod test {
4878 use test_utils:: TempFile ;
4979
5080 #[ test]
51- fn renders_an_executable_that_outputs_the_given_stdout ( ) -> R < ( ) > {
52- let mock_executable = TempFile :: write_temp_script ( & create_mock_executable (
81+ fn creates_an_executable_that_outputs_the_given_stdout ( ) -> R < ( ) > {
82+ let mock_executable = ExecutableMock :: new (
5383 & Context :: new_mock ( ) ,
5484 Config {
5585 stdout : b"foo" . to_vec ( ) ,
5686 exitcode : 0 ,
5787 } ,
58- ) ?) ? ;
88+ ) ?;
5989 let output = Command :: new ( mock_executable. path ( ) ) . output ( ) ?;
6090 assert_eq ! ( output. stdout, b"foo" ) ;
6191 Ok ( ( ) )
6292 }
6393
6494 #[ test]
65- fn renders_an_executable_that_exits_with_the_given_exitcode ( ) -> R < ( ) > {
66- let mock_executable = TempFile :: write_temp_script ( & create_mock_executable (
95+ fn creates_an_executable_that_exits_with_the_given_exitcode ( ) -> R < ( ) > {
96+ let mock_executable = ExecutableMock :: new (
6797 & Context :: new_mock ( ) ,
6898 Config {
6999 stdout : b"foo" . to_vec ( ) ,
70100 exitcode : 42 ,
71101 } ,
72- ) ?) ? ;
102+ ) ?;
73103 let output = Command :: new ( mock_executable. path ( ) ) . output ( ) ?;
74104 assert_eq ! ( output. status. code( ) , Some ( 42 ) ) ;
75105 Ok ( ( ) )
0 commit comments