]> git.lizzy.rs Git - rust.git/commitdiff
Add shims for mkdir and rmdir
authorDavid Cook <divergentdave@gmail.com>
Sat, 25 Jan 2020 00:56:23 +0000 (18:56 -0600)
committerDavid Cook <divergentdave@gmail.com>
Sun, 23 Feb 2020 21:02:49 +0000 (15:02 -0600)
src/shims/foreign_items/posix.rs
src/shims/fs.rs
tests/run-pass/fs.rs

index a8b4aad8819b0c456c0366795c0c3c793f43ccc5..e520e23199e3cead5ed6e8a8c432f03886b74a9c 100644 (file)
@@ -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)?;
index aa562926686dc542aa133475c45968cb7ba8d8b5..45471a638a18eaf8292246ff82ea6d41faa9fc0f 100644 (file)
@@ -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
index a6ce8627cde7c24003b3d0f62e935b90f7e43f6a..7f920d8c19d8ef9eb50d6723aafad7ac5d9ea1bf 100644 (file)
@@ -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());
+}