Skip to content

Commit f76f8ce

Browse files
committed
Correct fcntl behavior
1 parent d73fae1 commit f76f8ce

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

src/shims/fs.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::*;
99

1010
pub struct FileHandle {
1111
file: File,
12-
flag: i32,
1312
}
1413

1514
pub struct FileHandler {
@@ -79,13 +78,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
7978
}
8079
let o_cloexec = this.eval_libc_i32("O_CLOEXEC")?;
8180
if flag & o_cloexec != 0 {
82-
// This flag is a noop for now because `std` already sets it.
81+
// We do not need to do anything for this flag because `std` already sets it.
82+
// (Technically we do not support *not* setting this flag, but we ignore that.)
8383
mirror |= o_cloexec;
8484
}
8585
// If `flag` is not equal to `mirror`, there is an unsupported option enabled in `flag`,
8686
// then we throw an error.
8787
if flag != mirror {
88-
throw_unsup_format!("unsupported flags {:#x}", flag);
88+
throw_unsup_format!("unsupported flags {:#x}", flag & !mirror);
8989
}
9090

9191
let path_bytes = this
@@ -97,7 +97,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9797
let fd = options.open(path).map(|file| {
9898
let mut fh = &mut this.machine.file_handler;
9999
fh.low += 1;
100-
fh.handles.insert(fh.low, FileHandle { file, flag });
100+
fh.handles.insert(fh.low, FileHandle { file });
101101
fh.low
102102
});
103103

@@ -108,7 +108,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
108108
&mut self,
109109
fd_op: OpTy<'tcx, Tag>,
110110
cmd_op: OpTy<'tcx, Tag>,
111-
_arg_op: Option<OpTy<'tcx, Tag>>,
111+
_arg1_op: Option<OpTy<'tcx, Tag>>,
112112
) -> InterpResult<'tcx, i32> {
113113
let this = self.eval_context_mut();
114114

@@ -120,7 +120,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
120120
let cmd = this.read_scalar(cmd_op)?.to_i32()?;
121121
// We only support getting the flags for a descriptor
122122
if cmd == this.eval_libc_i32("F_GETFD")? {
123-
this.get_handle_and(fd, |handle| Ok(handle.flag))
123+
// Currently this is the only flag that `F_GETFD` returns. It is OK to just return the
124+
// `FD_CLOEXEC` value without checking if the flag is set for the file because `std`
125+
// always sets this flag when opening a file. However we still need to check that the
126+
// file itself is open.
127+
this.get_handle_and(fd, |_| Ok(0))?;
128+
this.eval_libc_i32("FD_CLOEXEC")
124129
} else {
125130
throw_unsup_format!("The {:#x} command is not supported for `fcntl`)", cmd);
126131
}

0 commit comments

Comments
 (0)