Skip to content

Commit 0a803c9

Browse files
committed
Auto merge of #1158 - divergentdave:shim-rename, r=RalfJung
Add shim for rename This adds a straightforward shim for rename, which is used by `std::fs::rename`. Testing is included. As a heads up, I expect one or two merge conflicts between my PRs, since some of them touch the same `use` statements, or add items near the same places. I'll rebase and fix them as they come up.
2 parents ded5a52 + 9186812 commit 0a803c9

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

src/shims/foreign_items.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
521521
this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
522522
}
523523

524+
"rename" => {
525+
let result = this.rename(args[0], args[1])?;
526+
this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
527+
}
528+
524529
"clock_gettime" => {
525530
let result = this.clock_gettime(args[0], args[1])?;
526531
this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;

src/shims/fs.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::HashMap;
22
use std::convert::{TryFrom, TryInto};
3-
use std::fs::{remove_file, File, OpenOptions};
3+
use std::fs::{remove_file, rename, File, OpenOptions};
44
use std::io::{Read, Seek, SeekFrom, Write};
55
use std::path::PathBuf;
66
use std::time::SystemTime;
@@ -582,6 +582,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
582582
this.set_last_error(ebadf)?;
583583
Ok((-1).into())
584584
}
585+
586+
fn rename(
587+
&mut self,
588+
oldpath_op: OpTy<'tcx, Tag>,
589+
newpath_op: OpTy<'tcx, Tag>,
590+
) -> InterpResult<'tcx, i32> {
591+
let this = self.eval_context_mut();
592+
593+
this.check_no_isolation("rename")?;
594+
595+
let oldpath_scalar = this.read_scalar(oldpath_op)?.not_undef()?;
596+
let newpath_scalar = this.read_scalar(newpath_op)?.not_undef()?;
597+
598+
if this.is_null(oldpath_scalar)? || this.is_null(newpath_scalar)? {
599+
let efault = this.eval_libc("EFAULT")?;
600+
this.set_last_error(efault)?;
601+
return Ok(-1);
602+
}
603+
604+
let oldpath = this.read_os_str_from_c_str(oldpath_scalar)?;
605+
let newpath = this.read_os_str_from_c_str(newpath_scalar)?;
606+
607+
let result = rename(oldpath, newpath).map(|_| 0);
608+
609+
this.try_unwrap_io_result(result)
610+
}
585611
}
586612

587613
/// Extracts the number of seconds and nanoseconds elapsed between `time` and the unix epoch when

tests/run-pass/fs.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// ignore-windows: File handling is not implemented yet
22
// compile-flags: -Zmiri-disable-isolation
33

4-
use std::fs::{File, remove_file};
4+
use std::fs::{File, remove_file, rename};
55
use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom};
66
use std::path::{PathBuf, Path};
77

@@ -82,6 +82,19 @@ fn main() {
8282
// Removing file should succeed.
8383
remove_file(&path).unwrap();
8484

85+
// Renaming a file should succeed.
86+
let path1 = tmp.join("rename_source.txt");
87+
let path2 = tmp.join("rename_destination.txt");
88+
// Clean files for robustness.
89+
remove_file(&path1).ok();
90+
remove_file(&path2).ok();
91+
let file = File::create(&path1).unwrap();
92+
drop(file);
93+
rename(&path1, &path2).unwrap();
94+
assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
95+
assert!(path2.metadata().unwrap().is_file());
96+
remove_file(&path2).unwrap();
97+
8598
// The two following tests also check that the `__errno_location()` shim is working properly.
8699
// Opening a non-existing file should fail with a "not found" error.
87100
assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());

0 commit comments

Comments
 (0)