this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
}
+ "rename" => {
+ let result = this.rename(args[0], args[1])?;
+ this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
+ }
+
"clock_gettime" => {
let result = this.clock_gettime(args[0], args[1])?;
this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
-use std::fs::{remove_file, File, OpenOptions};
+use std::fs::{remove_file, rename, File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::PathBuf;
use std::time::SystemTime;
this.set_last_error(ebadf)?;
Ok((-1).into())
}
+
+ fn rename(
+ &mut self,
+ oldpath_op: OpTy<'tcx, Tag>,
+ newpath_op: OpTy<'tcx, Tag>,
+ ) -> InterpResult<'tcx, i32> {
+ let this = self.eval_context_mut();
+
+ this.check_no_isolation("rename")?;
+
+ let oldpath_scalar = this.read_scalar(oldpath_op)?.not_undef()?;
+ let newpath_scalar = this.read_scalar(newpath_op)?.not_undef()?;
+
+ if this.is_null(oldpath_scalar)? || this.is_null(newpath_scalar)? {
+ let efault = this.eval_libc("EFAULT")?;
+ this.set_last_error(efault)?;
+ return Ok(-1);
+ }
+
+ let oldpath = this.read_os_str_from_c_str(oldpath_scalar)?;
+ let newpath = this.read_os_str_from_c_str(newpath_scalar)?;
+
+ let result = rename(oldpath, newpath).map(|_| 0);
+
+ 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};
+use std::fs::{File, remove_file, rename};
use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom};
use std::path::{PathBuf, Path};
// Removing file should succeed.
remove_file(&path).unwrap();
+ // Renaming a file should succeed.
+ let path1 = tmp.join("rename_source.txt");
+ let path2 = tmp.join("rename_destination.txt");
+ // Clean files for robustness.
+ remove_file(&path1).ok();
+ remove_file(&path2).ok();
+ let file = File::create(&path1).unwrap();
+ drop(file);
+ rename(&path1, &path2).unwrap();
+ assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
+ assert!(path2.metadata().unwrap().is_file());
+ remove_file(&path2).unwrap();
+
// The two following tests also check that the `__errno_location()` shim is working properly.
// Opening a non-existing file should fail with a "not found" error.
assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());