this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
}
+ "symlink" => {
+ let result = this.symlink(args[0], args[1])?;
+ this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
+ }
+
"stat$INODE64" => {
let result = this.stat(args[0], args[1])?;
this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
this.try_unwrap_io_result(result)
}
+ fn symlink(
+ &mut self,
+ target_op: OpTy<'tcx, Tag>,
+ linkpath_op: OpTy<'tcx, Tag>
+ ) -> InterpResult<'tcx, i32> {
+ #[cfg(target_family = "unix")]
+ fn create_link(src: PathBuf, dst: PathBuf) -> std::io::Result<()> {
+ std::os::unix::fs::symlink(src, dst)
+ }
+
+ #[cfg(target_family = "windows")]
+ fn create_link(src: PathBuf, dst: PathBuf) -> std::io::Result<()> {
+ use std::os::windows::fs;
+ if src.is_dir() {
+ fs::symlink_dir(src, dst)
+ } else {
+ fs::symlink(src, dst)
+ }
+ }
+
+ let this = self.eval_context_mut();
+
+ this.check_no_isolation("symlink")?;
+
+ let target = this.read_os_str_from_c_str(this.read_scalar(target_op)?.not_undef()?)?.into();
+ let linkpath = this.read_os_str_from_c_str(this.read_scalar(linkpath_op)?.not_undef()?)?.into();
+
+ this.try_unwrap_io_result(create_link(target, linkpath).map(|_| 0))
+ }
+
fn stat(
&mut self,
path_op: OpTy<'tcx, Tag>,
let metadata = if follow_symlink {
std::fs::metadata(path)
} else {
- // FIXME: metadata for symlinks need testing.
std::fs::symlink_metadata(path)
};
// Test that metadata of an absolute path is correct.
test_metadata(bytes, &path).unwrap();
// Test that metadata of a relative path is correct.
- std::env::set_current_dir(tmp).unwrap();
+ std::env::set_current_dir(&tmp).unwrap();
test_metadata(bytes, &filename).unwrap();
+ // Creating a symbolic link should succeed
+ let symlink_path = tmp.join("miri_test_fs_symlink.txt");
+ std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
+ // Test that the symbolic link has the same contents as the file.
+ let mut symlink_file = File::open(&symlink_path).unwrap();
+ let mut contents = Vec::new();
+ symlink_file.read_to_end(&mut contents).unwrap();
+ assert_eq!(bytes, contents.as_slice());
+ // Test that metadata of a symbolic link is correct.
+ test_metadata(bytes, &symlink_path).unwrap();
+ // Test that the metadata of a symbolic link is correct when not following it.
+ assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
+ // Removing symbolic link should succeed.
+ remove_file(&symlink_path).unwrap();
+
// Removing file should succeed.
remove_file(&path).unwrap();