this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
}
+ "mkdir" => {
+ let result = this.mkdir(args[0], args[1])?;
+ this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
+ }
+
+ "rmdir" => {
+ let result = this.rmdir(args[0])?;
+ this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
+ }
+
"lseek" | "lseek64" => {
let result = this.lseek64(args[0], args[1], args[2])?;
this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
use std::collections::BTreeMap;
use std::convert::{TryFrom, TryInto};
-use std::fs::{remove_file, rename, File, OpenOptions};
+use std::fs::{remove_dir, remove_file, rename, DirBuilder, File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::PathBuf;
use std::time::SystemTime;
this.try_unwrap_io_result(result)
}
+
+ fn mkdir(
+ &mut self,
+ path_op: OpTy<'tcx, Tag>,
+ mode_op: OpTy<'tcx, Tag>,
+ ) -> InterpResult<'tcx, i32> {
+ let this = self.eval_context_mut();
+
+ this.check_no_isolation("mkdir")?;
+
+ let mode = this.read_scalar(mode_op)?.to_u32()?;
+
+ let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
+
+ let mut builder = DirBuilder::new();
+ #[cfg(target_family = "unix")]
+ {
+ use std::os::unix::fs::DirBuilderExt;
+ builder.mode(mode);
+ }
+ let result = builder.create(path).map(|_| 0i32);
+
+ this.try_unwrap_io_result(result)
+ }
+
+ fn rmdir(
+ &mut self,
+ path_op: OpTy<'tcx, Tag>,
+ ) -> InterpResult<'tcx, i32> {
+ let this = self.eval_context_mut();
+
+ this.check_no_isolation("rmdir")?;
+
+ let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
+
+ let result = remove_dir(path).map(|_| 0i32);
+
+ this.try_unwrap_io_result(result)
+ }
}
/// Extracts the number of seconds and nanoseconds elapsed between `time` and the unix epoch when
// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation
-use std::fs::{File, remove_file, rename};
+use std::fs::{File, create_dir, remove_dir, remove_dir_all, remove_file, rename};
use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom};
use std::path::{PathBuf, Path};
test_symlink();
test_errors();
test_rename();
+ test_directory();
}
/// Prepare: compute filename and make sure the file does not exist.
path
}
+/// Prepare directory: compute directory name and make sure it does not exist.
+fn prepare_dir(dirname: &str) -> PathBuf {
+ let tmp = std::env::temp_dir();
+ 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);
remove_file(&path2).unwrap();
}
+
+fn test_directory() {
+ let dir_path = prepare_dir("miri_test_fs_dir");
+ // Creating a directory should succeed.
+ create_dir(&dir_path).unwrap();
+ // Test that the metadata of a directory is correct.
+ assert!(dir_path.metadata().unwrap().is_dir());
+ // Deleting the directory should succeed.
+ remove_dir(&dir_path).unwrap();
+ // Reading the metadata of a non-existent file should fail with a "not found" error.
+ assert_eq!(ErrorKind::NotFound, check_metadata(&[], &dir_path).unwrap_err().kind());
+}