@@ -28,7 +28,7 @@ impl Default for FileHandler {
28
28
FileHandler {
29
29
handles : Default :: default ( ) ,
30
30
// 0, 1 and 2 are reserved for stdin, stdout and stderr.
31
- low : 3 ,
31
+ low : 2 ,
32
32
}
33
33
}
34
34
}
@@ -120,7 +120,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
120
120
& mut self ,
121
121
fd_op : OpTy < ' tcx , Tag > ,
122
122
cmd_op : OpTy < ' tcx , Tag > ,
123
- _arg1_op : Option < OpTy < ' tcx , Tag > > ,
123
+ arg_op : Option < OpTy < ' tcx , Tag > > ,
124
124
) -> InterpResult < ' tcx , i32 > {
125
125
let this = self . eval_context_mut ( ) ;
126
126
@@ -139,6 +139,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
139
139
} else {
140
140
this. handle_not_found ( )
141
141
}
142
+ } else if cmd == this. eval_libc_i32 ( "F_DUPFD" ) ? || cmd == this. eval_libc_i32 ( "F_DUPFD_CLOEXEC" ) ? {
143
+ let arg = match arg_op {
144
+ Some ( arg_op) => this. read_scalar ( arg_op) ?. to_i32 ( ) ?,
145
+ None => throw_unsup_format ! ( "fcntl with command F_DUPFD or F_DUPFD_CLOEXEC requires a third argument" ) ,
146
+ } ;
147
+ let fh = & mut this. machine . file_handler ;
148
+ let ( file_result, writable) = match fh. handles . get ( & fd) {
149
+ Some ( original) => ( original. file . try_clone ( ) , original. writable ) ,
150
+ None => return this. handle_not_found ( ) ,
151
+ } ;
152
+ let fd_result = file_result. map ( |duplicated| {
153
+ let new_fd = std:: cmp:: max ( fh. low + 1 , arg) ;
154
+ fh. low = new_fd;
155
+ fh. handles . insert ( fh. low , FileHandle { file : duplicated, writable } ) . unwrap_none ( ) ;
156
+ new_fd
157
+ } ) ;
158
+ this. try_unwrap_io_result ( fd_result)
142
159
} else {
143
160
throw_unsup_format ! ( "The {:#x} command is not supported for `fcntl`)" , cmd) ;
144
161
}
0 commit comments