diff --git a/src/shims/fs.rs b/src/shims/fs.rs index 5f8be275b2e4..04ca538f8b6b 100644 --- a/src/shims/fs.rs +++ b/src/shims/fs.rs @@ -288,8 +288,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } let o_creat = this.eval_libc_i32("O_CREAT")?; if flag & o_creat != 0 { - options.create(true); mirror |= o_creat; + + let o_excl = this.eval_libc_i32("O_EXCL")?; + if flag & o_excl != 0 { + mirror |= o_excl; + options.create_new(true); + } else { + options.create(true); + } } let o_cloexec = this.eval_libc_i32("O_CLOEXEC")?; if flag & o_cloexec != 0 { diff --git a/tests/run-pass/fs.rs b/tests/run-pass/fs.rs index 104ba46c3e45..d8b6e5b44575 100644 --- a/tests/run-pass/fs.rs +++ b/tests/run-pass/fs.rs @@ -1,13 +1,16 @@ // ignore-windows: File handling is not implemented yet // compile-flags: -Zmiri-disable-isolation -use std::fs::{File, create_dir, read_dir, remove_dir, remove_dir_all, remove_file, rename}; +use std::fs::{ + File, create_dir, OpenOptions, read_dir, remove_dir, remove_dir_all, remove_file, rename, +}; use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom}; use std::path::{PathBuf, Path}; fn main() { test_file(); test_file_clone(); + test_file_create_new(); test_seek(); test_metadata(); test_symlink(); @@ -85,6 +88,20 @@ fn test_file_clone() { remove_file(&path).unwrap(); } +fn test_file_create_new() { + let path = prepare("miri_test_fs_file_create_new.txt"); + + // Creating a new file that doesn't yet exist should succeed. + OpenOptions::new().write(true).create_new(true).open(&path).unwrap(); + // Creating a new file that already exists should fail. + assert_eq!(ErrorKind::AlreadyExists, OpenOptions::new().write(true).create_new(true).open(&path).unwrap_err().kind()); + // Optionally creating a new file that already exists should succeed. + OpenOptions::new().write(true).create(true).open(&path).unwrap(); + + // Clean up + remove_file(&path).unwrap(); +} + fn test_seek() { let bytes = b"Hello, entire World!\n"; let path = prepare_with_content("miri_test_fs_seek.txt", bytes);