Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions src/shims/unix/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,13 @@ impl FileDescription for NullOutput {
}

#[derive(Clone, Debug)]
pub struct FileDescriptor(Rc<RefCell<Box<dyn FileDescription>>>);
pub struct FileDescriptionRef(Rc<RefCell<Box<dyn FileDescription>>>);

impl FileDescriptionRef {
fn new(fd: impl FileDescription) -> Self {
FileDescriptionRef(Rc::new(RefCell::new(Box::new(fd))))
}

impl FileDescriptor {
pub fn borrow(&self) -> Ref<'_, dyn FileDescription> {
Ref::map(self.0.borrow(), |fd| fd.as_ref())
}
Expand All @@ -213,7 +217,7 @@ impl FileDescriptor {
/// The file descriptor table
#[derive(Debug)]
pub struct FdTable {
pub fds: BTreeMap<i32, FileDescriptor>,
fds: BTreeMap<i32, FileDescriptionRef>,
}

impl VisitProvenance for FdTable {
Expand All @@ -239,14 +243,14 @@ impl FdTable {
fds
}

/// Insert a file descriptor to the FdTable.
pub fn insert_fd<T: FileDescription>(&mut self, fd: T) -> i32 {
let file_handle = FileDescriptor(Rc::new(RefCell::new(Box::new(fd))));
/// Insert a new file description to the FdTable.
pub fn insert_fd(&mut self, fd: impl FileDescription) -> i32 {
let file_handle = FileDescriptionRef::new(fd);
self.insert_fd_with_min_fd(file_handle, 0)
}

/// Insert a new FD that is at least `min_fd`.
pub fn insert_fd_with_min_fd(&mut self, file_handle: FileDescriptor, min_fd: i32) -> i32 {
fn insert_fd_with_min_fd(&mut self, file_handle: FileDescriptionRef, min_fd: i32) -> i32 {
// Find the lowest unused FD, starting from min_fd. If the first such unused FD is in
// between used FDs, the find_map combinator will return it. If the first such unused FD
// is after all other used FDs, the find_map combinator will return None, and we will use
Expand Down Expand Up @@ -282,12 +286,12 @@ impl FdTable {
Some(fd.borrow_mut())
}

pub fn dup(&self, fd: i32) -> Option<FileDescriptor> {
pub fn dup(&self, fd: i32) -> Option<FileDescriptionRef> {
let fd = self.fds.get(&fd)?;
Some(fd.clone())
}

pub fn remove(&mut self, fd: i32) -> Option<FileDescriptor> {
pub fn remove(&mut self, fd: i32) -> Option<FileDescriptionRef> {
self.fds.remove(&fd)
}

Expand Down Expand Up @@ -316,9 +320,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
if new_fd != old_fd {
// Close new_fd if it is previously opened.
// If old_fd and new_fd point to the same description, then `dup_fd` ensures we keep the underlying file description alive.
if let Some(file_descriptor) = this.machine.fds.fds.insert(new_fd, dup_fd) {
if let Some(file_description) = this.machine.fds.fds.insert(new_fd, dup_fd) {
// Ignore close error (not interpreter's) according to dup2() doc.
file_descriptor.close(this.machine.communicate())?.ok();
file_description.close(this.machine.communicate())?.ok();
}
}
Ok(new_fd)
Expand Down Expand Up @@ -385,10 +389,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {

let fd = this.read_scalar(fd_op)?.to_i32()?;

let Some(file_descriptor) = this.machine.fds.remove(fd) else {
let Some(file_description) = this.machine.fds.remove(fd) else {
return Ok(Scalar::from_i32(this.fd_not_found()?));
};
let result = file_descriptor.close(this.machine.communicate())?;
let result = file_description.close(this.machine.communicate())?;
// return `0` if close is successful
let result = result.map(|()| 0i32);
Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
Expand Down
40 changes: 20 additions & 20 deletions src/shims/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,13 +483,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {

let communicate = this.machine.communicate();

let Some(mut file_descriptor) = this.machine.fds.get_mut(fd) else {
let Some(mut file_description) = this.machine.fds.get_mut(fd) else {
return Ok(Scalar::from_i64(this.fd_not_found()?));
};
let result = file_descriptor
let result = file_description
.seek(communicate, seek_from)?
.map(|offset| i64::try_from(offset).unwrap());
drop(file_descriptor);
drop(file_description);

let result = this.try_unwrap_io_result(result)?;
Ok(Scalar::from_i64(result))
Expand Down Expand Up @@ -1176,30 +1176,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
return Ok(Scalar::from_i32(this.fd_not_found()?));
}

let Some(file_descriptor) = this.machine.fds.get(fd) else {
let Some(file_description) = this.machine.fds.get(fd) else {
return Ok(Scalar::from_i32(this.fd_not_found()?));
};

// FIXME: Support ftruncate64 for all FDs
let FileHandle { file, writable } =
file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
file_description.downcast_ref::<FileHandle>().ok_or_else(|| {
err_unsup_format!("`ftruncate64` is only supported on file-backed file descriptors")
})?;

if *writable {
if let Ok(length) = length.try_into() {
let result = file.set_len(length);
drop(file_descriptor);
drop(file_description);
let result = this.try_unwrap_io_result(result.map(|_| 0i32))?;
Ok(Scalar::from_i32(result))
} else {
drop(file_descriptor);
drop(file_description);
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
Ok(Scalar::from_i32(-1))
}
} else {
drop(file_descriptor);
drop(file_description);
// The file is not writable
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
Expand Down Expand Up @@ -1229,16 +1229,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {

fn ffullsync_fd(&mut self, fd: i32) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
let Some(file_descriptor) = this.machine.fds.get(fd) else {
let Some(file_description) = this.machine.fds.get(fd) else {
return Ok(this.fd_not_found()?);
};
// Only regular files support synchronization.
let FileHandle { file, writable } =
file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
file_description.downcast_ref::<FileHandle>().ok_or_else(|| {
err_unsup_format!("`fsync` is only supported on file-backed file descriptors")
})?;
let io_result = maybe_sync_file(file, *writable, File::sync_all);
drop(file_descriptor);
drop(file_description);
this.try_unwrap_io_result(io_result)
}

Expand All @@ -1254,16 +1254,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
return this.fd_not_found();
}

let Some(file_descriptor) = this.machine.fds.get(fd) else {
let Some(file_description) = this.machine.fds.get(fd) else {
return Ok(this.fd_not_found()?);
};
// Only regular files support synchronization.
let FileHandle { file, writable } =
file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
file_description.downcast_ref::<FileHandle>().ok_or_else(|| {
err_unsup_format!("`fdatasync` is only supported on file-backed file descriptors")
})?;
let io_result = maybe_sync_file(file, *writable, File::sync_data);
drop(file_descriptor);
drop(file_description);
this.try_unwrap_io_result(io_result)
}

Expand Down Expand Up @@ -1302,18 +1302,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
return Ok(Scalar::from_i32(this.fd_not_found()?));
}

let Some(file_descriptor) = this.machine.fds.get(fd) else {
let Some(file_description) = this.machine.fds.get(fd) else {
return Ok(Scalar::from_i32(this.fd_not_found()?));
};
// Only regular files support synchronization.
let FileHandle { file, writable } =
file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
file_description.downcast_ref::<FileHandle>().ok_or_else(|| {
err_unsup_format!(
"`sync_data_range` is only supported on file-backed file descriptors"
)
})?;
let io_result = maybe_sync_file(file, *writable, File::sync_data);
drop(file_descriptor);
drop(file_description);
Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
}

Expand Down Expand Up @@ -1609,11 +1609,11 @@ impl FileMetadata {
ecx: &mut MiriInterpCx<'tcx>,
fd: i32,
) -> InterpResult<'tcx, Option<FileMetadata>> {
let Some(file_descriptor) = ecx.machine.fds.get(fd) else {
let Some(file_description) = ecx.machine.fds.get(fd) else {
return ecx.fd_not_found().map(|_: i32| None);
};

let file = &file_descriptor
let file = &file_description
.downcast_ref::<FileHandle>()
.ok_or_else(|| {
err_unsup_format!(
Expand All @@ -1623,7 +1623,7 @@ impl FileMetadata {
.file;

let metadata = file.metadata();
drop(file_descriptor);
drop(file_description);
FileMetadata::from_meta(ecx, metadata)
}

Expand Down