diff options
| author | bors <bors@rust-lang.org> | 2022-12-09 11:28:20 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-12-09 11:28:20 +0000 |
| commit | 816ec1ba350a1749b61574c81326cb91ed80bb4e (patch) | |
| tree | 1d17e04addc1bcb9310ef1173871ecb59ba3b2f0 | |
| parent | 552b63c1619498f1a17fd482f4bb87815d8fdc48 (diff) | |
| parent | 20a4c7371710ed6cd219fc80580f9855917f93bf (diff) | |
| download | rust-816ec1ba350a1749b61574c81326cb91ed80bb4e.tar.gz rust-816ec1ba350a1749b61574c81326cb91ed80bb4e.zip | |
Auto merge of #2718 - Pointerbender:o_tmpfile_flag, r=oli-obk
add graceful shim for the custom `O_TMPFILE` file opening flag plus test case I'm trying if I can get the [`tempfile`](https://crates.io/crates/tempfile) crate to work nicely with miri. Right now miri errors out due to an unsupported flag `O_TMPFILE` (= `0x410000`) passed to [`OpenOptions::custom_flags`](https://github.com/Stebalien/tempfile/blob/92ae3e9d6e82bdcfcf114be459d234d3602be2d4/src/file/imp/unix.rs#L71-L86). Interestingly, `tempfile` has a fallback in case the underlying file system does not support the `O_TMPFILE` flag, in which case `open`/`open64` is expected to return the error code `EOPNOTSUPP` (= `95`). This PR adds support for this scenario and also includes a test case (relevant [zulip](https://rust-lang.zulipchat.com/#narrow/stream/269128-miri/topic/miri.20and.20the.20.60tempfile.60.20crate) discussion).
| -rw-r--r-- | src/tools/miri/src/shims/unix/fs.rs | 9 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass-dep/shims/libc-fs.rs | 32 |
2 files changed, 40 insertions, 1 deletions
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 988627db561..bf99412af65 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -605,6 +605,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // (Technically we do not support *not* setting this flag, but we ignore that.) mirror |= o_cloexec; } + if this.tcx.sess.target.os == "linux" { + let o_tmpfile = this.eval_libc_i32("O_TMPFILE")?; + if flag & o_tmpfile != 0 { + // if the flag contains `O_TMPFILE` then we return a graceful error + let eopnotsupp = this.eval_libc("EOPNOTSUPP")?; + this.set_last_error(eopnotsupp)?; + return Ok(-1); + } + } // If `flag` is not equal to `mirror`, there is an unsupported option enabled in `flag`, // then we throw an error. if flag != mirror { diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs index acf16ecb7e0..93c0fad9c10 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs @@ -6,7 +6,7 @@ use std::convert::TryInto; use std::ffi::CString; -use std::fs::{canonicalize, remove_file, File}; +use std::fs::{canonicalize, remove_dir_all, remove_file, File}; use std::io::{Error, ErrorKind, Write}; use std::os::unix::ffi::OsStrExt; use std::path::PathBuf; @@ -18,6 +18,8 @@ fn main() { test_file_open_unix_allow_two_args(); test_file_open_unix_needs_three_args(); test_file_open_unix_extra_third_arg(); + #[cfg(target_os = "linux")] + test_o_tmpfile_flag(); } fn tmp() -> PathBuf { @@ -45,6 +47,15 @@ fn prepare(filename: &str) -> PathBuf { path } +/// Prepare directory: compute directory name and make sure it does not exist. +#[allow(unused)] +fn prepare_dir(dirname: &str) -> PathBuf { + let path = tmp().join(&dirname); + // Clean the directory for robustness. + remove_dir_all(&path).ok(); + path +} + /// Prepare like above, and also write some initial content to the file. fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf { let path = prepare(filename); @@ -135,3 +146,22 @@ fn test_readlink() { assert_eq!(res, -1); assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); } + +#[cfg(target_os = "linux")] +fn test_o_tmpfile_flag() { + use std::fs::{create_dir, OpenOptions}; + use std::os::unix::fs::OpenOptionsExt; + let dir_path = prepare_dir("miri_test_fs_dir"); + create_dir(&dir_path).unwrap(); + // test that the `O_TMPFILE` custom flag gracefully errors instead of stopping execution + assert_eq!( + Some(libc::EOPNOTSUPP), + OpenOptions::new() + .read(true) + .write(true) + .custom_flags(libc::O_TMPFILE) + .open(dir_path) + .unwrap_err() + .raw_os_error(), + ); +} |
