|
1 | 1 | //! General management of file descriptors, and support for |
2 | 2 | //! standard file descriptors (stdin/stdout/stderr). |
3 | 3 |
|
| 4 | +use std::io; |
4 | 5 | use std::io::ErrorKind; |
5 | 6 |
|
6 | 7 | use rustc_abi::Size; |
7 | 8 |
|
8 | 9 | use crate::helpers::check_min_arg_count; |
9 | | -use crate::shims::files::FlockOp; |
| 10 | +use crate::shims::files::FileDescription; |
10 | 11 | use crate::shims::unix::linux_like::epoll::EpollReadyEvents; |
11 | 12 | use crate::shims::unix::*; |
12 | 13 | use crate::*; |
13 | 14 |
|
| 15 | +#[derive(Debug, Clone, Copy, Eq, PartialEq)] |
| 16 | +pub(crate) enum FlockOp { |
| 17 | + SharedLock { nonblocking: bool }, |
| 18 | + ExclusiveLock { nonblocking: bool }, |
| 19 | + Unlock, |
| 20 | +} |
| 21 | + |
| 22 | +/// Represents unix-specific file descriptions. |
| 23 | +pub trait UnixFileDescription: FileDescription { |
| 24 | + /// Reads as much as possible into the given buffer `ptr` from a given offset. |
| 25 | + /// `len` indicates how many bytes we should try to read. |
| 26 | + /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error. |
| 27 | + fn pread<'tcx>( |
| 28 | + &self, |
| 29 | + _communicate_allowed: bool, |
| 30 | + _offset: u64, |
| 31 | + _ptr: Pointer, |
| 32 | + _len: usize, |
| 33 | + _dest: &MPlaceTy<'tcx>, |
| 34 | + _ecx: &mut MiriInterpCx<'tcx>, |
| 35 | + ) -> InterpResult<'tcx> { |
| 36 | + throw_unsup_format!("cannot pread from {}", self.name()); |
| 37 | + } |
| 38 | + |
| 39 | + /// Writes as much as possible from the given buffer `ptr` starting at a given offset. |
| 40 | + /// `ptr` is the pointer to the user supplied read buffer. |
| 41 | + /// `len` indicates how many bytes we should try to write. |
| 42 | + /// `dest` is where the return value should be stored: number of bytes written, or `-1` in case of error. |
| 43 | + fn pwrite<'tcx>( |
| 44 | + &self, |
| 45 | + _communicate_allowed: bool, |
| 46 | + _ptr: Pointer, |
| 47 | + _len: usize, |
| 48 | + _offset: u64, |
| 49 | + _dest: &MPlaceTy<'tcx>, |
| 50 | + _ecx: &mut MiriInterpCx<'tcx>, |
| 51 | + ) -> InterpResult<'tcx> { |
| 52 | + throw_unsup_format!("cannot pwrite to {}", self.name()); |
| 53 | + } |
| 54 | + |
| 55 | + fn flock<'tcx>( |
| 56 | + &self, |
| 57 | + _communicate_allowed: bool, |
| 58 | + _op: FlockOp, |
| 59 | + ) -> InterpResult<'tcx, io::Result<()>> { |
| 60 | + throw_unsup_format!("cannot flock {}", self.name()); |
| 61 | + } |
| 62 | + |
| 63 | + /// Check the readiness of file description. |
| 64 | + fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { |
| 65 | + throw_unsup_format!("{}: epoll does not support this file description", self.name()); |
| 66 | + } |
| 67 | +} |
| 68 | + |
14 | 69 | impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} |
15 | 70 | pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
16 | 71 | fn dup(&mut self, old_fd_num: i32) -> InterpResult<'tcx, Scalar> { |
@@ -66,7 +121,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
66 | 121 | throw_unsup_format!("unsupported flags {:#x}", op); |
67 | 122 | }; |
68 | 123 |
|
69 | | - let result = fd.flock(this.machine.communicate(), parsed_op)?; |
| 124 | + let result = fd.as_unix().flock(this.machine.communicate(), parsed_op)?; |
70 | 125 | drop(fd); |
71 | 126 | // return `0` if flock is successful |
72 | 127 | let result = result.map(|()| 0i32); |
@@ -196,7 +251,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
196 | 251 | let Ok(offset) = u64::try_from(offset) else { |
197 | 252 | return this.set_last_error_and_return(LibcError("EINVAL"), dest); |
198 | 253 | }; |
199 | | - fd.pread(communicate, offset, buf, count, dest, this)? |
| 254 | + fd.as_unix().pread(communicate, offset, buf, count, dest, this)? |
200 | 255 | } |
201 | 256 | }; |
202 | 257 | interp_ok(()) |
@@ -236,7 +291,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
236 | 291 | let Ok(offset) = u64::try_from(offset) else { |
237 | 292 | return this.set_last_error_and_return(LibcError("EINVAL"), dest); |
238 | 293 | }; |
239 | | - fd.pwrite(communicate, buf, count, offset, dest, this)? |
| 294 | + fd.as_unix().pwrite(communicate, buf, count, offset, dest, this)? |
240 | 295 | } |
241 | 296 | }; |
242 | 297 | interp_ok(()) |
|
0 commit comments