impl<'mir, 'tcx: 'mir> EvalContextExtPrivate<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
- /// Emulate `stat` or `lstat` on `macos`. This function is not intended to be
- /// called directly from `emulate_foreign_item_by_name`, so it does not check if isolation is
- /// disabled or if the target OS is the correct one. Please use `macos_stat` or
- /// `macos_lstat` instead.
- fn macos_stat_or_lstat(
- &mut self,
- follow_symlink: bool,
- path_op: &OpTy<'tcx, Tag>,
- buf_op: &OpTy<'tcx, Tag>,
- ) -> InterpResult<'tcx, i32> {
- let this = self.eval_context_mut();
-
- let path_scalar = this.read_pointer(path_op)?;
- let path = this.read_path_from_c_str(path_scalar)?.into_owned();
-
- let metadata = match FileMetadata::from_path(this, &path, follow_symlink)? {
- Some(metadata) => metadata,
- None => return Ok(-1),
- };
- this.macos_stat_write_buf(metadata, buf_op)
- }
-
fn macos_stat_write_buf(
&mut self,
metadata: FileMetadata,
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
- // Reject if isolation is enabled.
- if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
- this.reject_in_isolation("`open`", reject_with)?;
- this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
- return Ok(-1);
- }
-
let flag = this.read_scalar(flag_op)?.to_i32()?;
// Get the mode. On macOS, the argument type `mode_t` is actually `u16`, but
let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
+ // Reject if isolation is enabled.
+ if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
+ this.reject_in_isolation("`open`", reject_with)?;
+ this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
+ return Ok(-1);
+ }
+
let fd = options.open(&path).map(|file| {
let fh = &mut this.machine.file_handler;
fh.insert_fd(Box::new(FileHandle { file, writable }))
fn fcntl(&mut self, args: &[OpTy<'tcx, Tag>]) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
- // Reject if isolation is enabled.
- if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
- this.reject_in_isolation("`fcntl`", reject_with)?;
- this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
- return Ok(-1);
- }
-
if args.len() < 2 {
throw_ub_format!(
"incorrect number of arguments for fcntl: got {}, expected at least 2",
}
let fd = this.read_scalar(&args[0])?.to_i32()?;
let cmd = this.read_scalar(&args[1])?.to_i32()?;
+
+ // Reject if isolation is enabled.
+ if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
+ this.reject_in_isolation("`fcntl`", reject_with)?;
+ this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
+ return Ok(-1);
+ }
+
// We only support getting the flags for a descriptor.
if cmd == this.eval_libc_i32("F_GETFD")? {
// Currently this is the only flag that `F_GETFD` returns. It is OK to just return the
fn unlink(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
+ let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`unlink`", reject_with)?;
return Ok(-1);
}
- let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
-
let result = remove_file(path).map(|_| 0);
this.try_unwrap_io_result(result)
}
}
let this = self.eval_context_mut();
+ let target = this.read_path_from_c_str(this.read_pointer(target_op)?)?;
+ let linkpath = this.read_path_from_c_str(this.read_pointer(linkpath_op)?)?;
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
return Ok(-1);
}
- let target = this.read_path_from_c_str(this.read_pointer(target_op)?)?;
- let linkpath = this.read_path_from_c_str(this.read_pointer(linkpath_op)?)?;
-
let result = create_link(&target, &linkpath).map(|_| 0);
this.try_unwrap_io_result(result)
}
let this = self.eval_context_mut();
this.assert_target_os("macos", "stat");
+ let path_scalar = this.read_pointer(path_op)?;
+ let path = this.read_path_from_c_str(path_scalar)?.into_owned();
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`stat`", reject_with)?;
}
// `stat` always follows symlinks.
- this.macos_stat_or_lstat(true, path_op, buf_op)
+ let metadata = match FileMetadata::from_path(this, &path, true)? {
+ Some(metadata) => metadata,
+ None => return Ok(-1),
+ };
+
+ this.macos_stat_write_buf(metadata, buf_op)
}
// `lstat` is used to get symlink metadata.
let this = self.eval_context_mut();
this.assert_target_os("macos", "lstat");
+ let path_scalar = this.read_pointer(path_op)?;
+ let path = this.read_path_from_c_str(path_scalar)?.into_owned();
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`lstat`", reject_with)?;
return Ok(-1);
}
- this.macos_stat_or_lstat(false, path_op, buf_op)
+ let metadata = match FileMetadata::from_path(this, &path, false)? {
+ Some(metadata) => metadata,
+ None => return Ok(-1),
+ };
+
+ this.macos_stat_write_buf(metadata, buf_op)
}
fn macos_fstat(
this.assert_target_os("macos", "fstat");
+ let fd = this.read_scalar(fd_op)?.to_i32()?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`fstat`", reject_with)?;
return this.handle_not_found();
}
- let fd = this.read_scalar(fd_op)?.to_i32()?;
-
let metadata = match FileMetadata::from_fd(this, fd)? {
Some(metadata) => metadata,
None => return Ok(-1),
// relative to CWD, `EACCES` is the most relevant.
this.eval_libc("EACCES")?
} else {
- // `dirfd` is set to target file, and `path` is
- // empty. `EACCES` would violate the spec.
+ // `dirfd` is set to target file, and `path` is empty
+ // (or we would have hit the `throw_unsup_format`
+ // above). `EACCES` would violate the spec.
+ assert!(empty_path_flag);
this.eval_libc("EBADF")?
};
this.set_last_error(ecode)?;
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
- // Reject if isolation is enabled.
- if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
- this.reject_in_isolation("`rename`", reject_with)?;
- this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
- return Ok(-1);
- }
-
let oldpath_ptr = this.read_pointer(oldpath_op)?;
let newpath_ptr = this.read_pointer(newpath_op)?;
let oldpath = this.read_path_from_c_str(oldpath_ptr)?;
let newpath = this.read_path_from_c_str(newpath_ptr)?;
+ // Reject if isolation is enabled.
+ if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
+ this.reject_in_isolation("`rename`", reject_with)?;
+ this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
+ return Ok(-1);
+ }
+
let result = rename(oldpath, newpath).map(|_| 0);
this.try_unwrap_io_result(result)
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
- // Reject if isolation is enabled.
- if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
- this.reject_in_isolation("`mkdir`", reject_with)?;
- this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
- return Ok(-1);
- }
-
#[cfg_attr(not(unix), allow(unused_variables))]
let mode = if this.tcx.sess.target.os == "macos" {
u32::from(this.read_scalar(mode_op)?.to_u16()?)
let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
+ // Reject if isolation is enabled.
+ if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
+ this.reject_in_isolation("`mkdir`", reject_with)?;
+ this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
+ return Ok(-1);
+ }
+
#[cfg_attr(not(unix), allow(unused_mut))]
let mut builder = DirBuilder::new();
fn rmdir(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
+ let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`rmdir`", reject_with)?;
return Ok(-1);
}
- let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
-
let result = remove_dir(path).map(|_| 0i32);
this.try_unwrap_io_result(result)
fn opendir(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, Scalar<Tag>> {
let this = self.eval_context_mut();
+ let name = this.read_path_from_c_str(this.read_pointer(name_op)?)?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`opendir`", reject_with)?;
return Ok(Scalar::null_ptr(this));
}
- let name = this.read_path_from_c_str(this.read_pointer(name_op)?)?;
-
let result = read_dir(name);
match result {
this.assert_target_os("linux", "readdir64_r");
+ let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`readdir64_r`", reject_with)?;
return this.handle_not_found();
}
- let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
-
let dir_iter = this.machine.dir_handler.streams.get_mut(&dirp).ok_or_else(|| {
err_unsup_format!("the DIR pointer passed to readdir64_r did not come from opendir")
})?;
this.assert_target_os("macos", "readdir_r");
+ let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`readdir_r`", reject_with)?;
return this.handle_not_found();
}
- let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
-
let dir_iter = this.machine.dir_handler.streams.get_mut(&dirp).ok_or_else(|| {
err_unsup_format!("the DIR pointer passed to readdir_r did not come from opendir")
})?;
fn closedir(&mut self, dirp_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
+ let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`closedir`", reject_with)?;
return this.handle_not_found();
}
- let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
-
if let Some(dir_iter) = this.machine.dir_handler.streams.remove(&dirp) {
drop(dir_iter);
Ok(0)
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
+ let fd = this.read_scalar(fd_op)?.to_i32()?;
+ let length = this.read_scalar(length_op)?.to_i64()?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`ftruncate64`", reject_with)?;
return this.handle_not_found();
}
- let fd = this.read_scalar(fd_op)?.to_i32()?;
- let length = this.read_scalar(length_op)?.to_i64()?;
if let Some(file_descriptor) = this.machine.file_handler.handles.get_mut(&fd) {
// FIXME: Support ftruncate64 for all FDs
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
let this = self.eval_context_mut();
+ let fd = this.read_scalar(fd_op)?.to_i32()?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`fsync`", reject_with)?;
return this.handle_not_found();
}
- let fd = this.read_scalar(fd_op)?.to_i32()?;
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
// FIXME: Support fsync for all FDs
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
fn fdatasync(&mut self, fd_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
+ let fd = this.read_scalar(fd_op)?.to_i32()?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`fdatasync`", reject_with)?;
return this.handle_not_found();
}
- let fd = this.read_scalar(fd_op)?.to_i32()?;
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
// FIXME: Support fdatasync for all FDs
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
- // Reject if isolation is enabled.
- if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
- this.reject_in_isolation("`sync_file_range`", reject_with)?;
- // Set error code as "EBADF" (bad fd)
- return this.handle_not_found();
- }
-
let fd = this.read_scalar(fd_op)?.to_i32()?;
let offset = this.read_scalar(offset_op)?.to_i64()?;
let nbytes = this.read_scalar(nbytes_op)?.to_i64()?;
return Ok(-1);
}
+ // Reject if isolation is enabled.
+ if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
+ this.reject_in_isolation("`sync_file_range`", reject_with)?;
+ // Set error code as "EBADF" (bad fd)
+ return this.handle_not_found();
+ }
+
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
// FIXME: Support sync_data_range for all FDs
let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
) -> InterpResult<'tcx, i64> {
let this = self.eval_context_mut();
+ let pathname = this.read_path_from_c_str(this.read_pointer(pathname_op)?)?;
+ let buf = this.read_pointer(buf_op)?;
+ let bufsize = this.read_scalar(bufsize_op)?.to_machine_usize(this)?;
+
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`readlink`", reject_with)?;
return Ok(-1);
}
- let pathname = this.read_path_from_c_str(this.read_pointer(pathname_op)?)?;
- let buf = this.read_pointer(buf_op)?;
- let bufsize = this.read_scalar(bufsize_op)?.to_machine_usize(this)?;
-
let result = std::fs::read_link(pathname);
match result {
Ok(resolved) => {