diff --git a/src/helpers.rs b/src/helpers.rs index 751d77a38978..5407eb120517 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -414,6 +414,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx use std::io::ErrorKind::*; let this = self.eval_context_mut(); let target = &this.tcx.sess.target.target; + let target_os = &target.target_os; let last_error = if target.options.target_family == Some("unix".to_owned()) { this.eval_libc(match e.kind() { ConnectionRefused => "ECONNREFUSED", @@ -434,15 +435,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx throw_unsup_format!("io error {} cannot be transformed into a raw os error", e) } })? - } else { + } else if target_os == "windows" { // FIXME: we have to finish implementing the Windows equivalent of this. this.eval_windows(match e.kind() { NotFound => "ERROR_FILE_NOT_FOUND", - _ => throw_unsup_format!( - "setting the last OS error from an io::Error is yet unsupported for {}.", - target.target_os - ) + _ => throw_unsup_format!("io error {} cannot be transformed into a raw os error", e) })? + } else { + throw_unsup_format!("setting the last OS error from an io::Error is unsupported for {}.", target_os) }; this.set_last_error(last_error) } diff --git a/src/shims/env.rs b/src/shims/env.rs index 78e7c37d9ce7..ce1be90ce699 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -357,7 +357,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn SetCurrentDirectoryW ( &mut self, path_op: OpTy<'tcx, Tag> // LPCTSTR - ) -> InterpResult<'tcx, i32> { // Returns BOOL(i32 in Windows) + ) -> InterpResult<'tcx, i32> { // Returns BOOL (i32 in Windows) let this = self.eval_context_mut(); this.assert_target_os("windows", "SetCurrentDirectoryW"); diff --git a/src/shims/os_str.rs b/src/shims/os_str.rs index c513be4a61f6..a182950f0065 100644 --- a/src/shims/os_str.rs +++ b/src/shims/os_str.rs @@ -179,7 +179,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_ref(); let os_str: &'a OsStr = this.read_os_str_from_c_str(scalar)?; - Ok(match convert_path_separator(os_str, &this.tcx.sess.target.target.target_os) { + Ok(match convert_path_separator(os_str, &this.tcx.sess.target.target.target_os, false) { Cow::Borrowed(x) => Cow::Borrowed(Path::new(x)), Cow::Owned(y) => Cow::Owned(PathBuf::from(y)), }) @@ -190,7 +190,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_ref(); let os_str: OsString = this.read_os_str_from_wide_str(scalar)?; - Ok(PathBuf::from(&convert_path_separator(&os_str, &this.tcx.sess.target.target.target_os))) + Ok(PathBuf::from(&convert_path_separator(&os_str, &this.tcx.sess.target.target.target_os, false))) } /// Write a Path to the machine memory (as a null-terminated sequence of bytes), @@ -202,7 +202,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx size: u64, ) -> InterpResult<'tcx, (bool, u64)> { let this = self.eval_context_mut(); - let os_str = convert_path_separator(path.as_os_str(), &this.tcx.sess.target.target.target_os); + let os_str = convert_path_separator(path.as_os_str(), &this.tcx.sess.target.target.target_os, true); this.write_os_str_to_c_str(&os_str, scalar, size) } @@ -215,35 +215,40 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx size: u64, ) -> InterpResult<'tcx, (bool, u64)> { let this = self.eval_context_mut(); - let os_str = convert_path_separator(path.as_os_str(), &this.tcx.sess.target.target.target_os); + let os_str = convert_path_separator(path.as_os_str(), &this.tcx.sess.target.target.target_os, true); this.write_os_str_to_wide_str(&os_str, scalar, size) } } /// Perform path separator conversion if needed. +/// if direction == true, Convert from 'host' to 'target'. +/// if direction == false, Convert from 'target' to 'host'. fn convert_path_separator<'a>( os_str: &'a OsStr, target_os: &str, + direction: bool, ) -> Cow<'a, OsStr> { #[cfg(windows)] return if target_os == "windows" { // Windows-on-Windows, all fine. Cow::Borrowed(os_str) } else { - // Unix target, Windows host. Need to convert host '\\' to target '/'. + // Unix target, Windows host. + let (from, to) = if direction { ('\\', '/') } else { ('/', '\\') }; let converted = os_str .encode_wide() - .map(|wchar| if wchar == '\\' as u16 { '/' as u16 } else { wchar }) + .map(|wchar| if wchar == from as u16 { to as u16 } else { wchar }) .collect::>(); Cow::Owned(OsString::from_wide(&converted)) }; #[cfg(unix)] return if target_os == "windows" { - // Windows target, Unix host. Need to convert host '/' to target '\'. + // Windows target, Unix host. + let (from, to) = if direction { ('/', '\\') } else { ('\\', '/') }; let converted = os_str .as_bytes() .iter() - .map(|&wchar| if wchar == '/' as u8 { '\\' as u8 } else { wchar }) + .map(|&wchar| if wchar == from as u8 { to as u8 } else { wchar }) .collect::>(); Cow::Owned(OsString::from_vec(converted)) } else {