From: David Cook Date: Sat, 25 Jan 2020 00:56:23 +0000 (-0600) Subject: Add shims for mkdir and rmdir X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=5b34f06bae63f9da496a907408789e17fc2ead0b;p=rust.git Add shims for mkdir and rmdir --- diff --git a/src/shims/foreign_items/posix.rs b/src/shims/foreign_items/posix.rs index a8b4aad8819..e520e23199e 100644 --- a/src/shims/foreign_items/posix.rs +++ b/src/shims/foreign_items/posix.rs @@ -109,6 +109,16 @@ fn emulate_foreign_item_by_name( 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)?; diff --git a/src/shims/fs.rs b/src/shims/fs.rs index aa562926686..45471a638a1 100644 --- a/src/shims/fs.rs +++ b/src/shims/fs.rs @@ -1,6 +1,6 @@ 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; @@ -722,6 +722,45 @@ fn rename( 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 diff --git a/tests/run-pass/fs.rs b/tests/run-pass/fs.rs index a6ce8627cde..7f920d8c19d 100644 --- a/tests/run-pass/fs.rs +++ b/tests/run-pass/fs.rs @@ -1,7 +1,7 @@ // 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}; @@ -13,6 +13,7 @@ fn main() { test_symlink(); test_errors(); test_rename(); + test_directory(); } /// Prepare: compute filename and make sure the file does not exist. @@ -24,6 +25,15 @@ fn prepare(filename: &str) -> PathBuf { 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); @@ -182,3 +192,15 @@ fn test_rename() { 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()); +}