X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fshims%2Fos_str.rs;h=a182950f0065533c919a4a314d748fe60631fdd0;hb=fe9ecb50d1dd1b8facd001e634449a9e8d52ad22;hp=316d5b0014a7ebe744b31d24efb51f6b59f36c74;hpb=ad14b684cc0a2aa9d9519786deec7475b78d4878;p=rust.git diff --git a/src/shims/os_str.rs b/src/shims/os_str.rs index 316d5b0014a..a182950f006 100644 --- a/src/shims/os_str.rs +++ b/src/shims/os_str.rs @@ -177,36 +177,24 @@ fn read_path_from_c_str<'a>(&'a self, scalar: Scalar) -> InterpResult<'tcx, 'mir: 'a, { let this = self.eval_context_ref(); - let os_str = this.read_os_str_from_c_str(scalar)?; + let os_str: &'a OsStr = this.read_os_str_from_c_str(scalar)?; - #[cfg(windows)] - return Ok(if this.tcx.sess.target.target.target_os == "windows" { - // Windows-on-Windows, all fine. - Cow::Borrowed(Path::new(os_str)) - } else { - // Unix target, Windows host. Need to convert target '/' to host '\'. - let converted = os_str - .encode_wide() - .map(|wchar| if wchar == '/' as u16 { '\\' as u16 } else { wchar }) - .collect::>(); - Cow::Owned(PathBuf::from(OsString::from_wide(&converted))) - }); - #[cfg(unix)] - return Ok(if this.tcx.sess.target.target.target_os == "windows" { - // Windows target, Unix host. Need to convert target '\' to host '/'. - let converted = os_str - .as_bytes() - .iter() - .map(|&wchar| if wchar == '/' as u8 { '\\' as u8 } else { wchar }) - .collect::>(); - Cow::Owned(PathBuf::from(OsString::from_vec(converted))) - } else { - // Unix-on-Unix, all is fine. - Cow::Borrowed(Path::new(os_str)) - }); + 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)), + }) + } + + /// Read a null-terminated sequence of `u16`s, and perform path separator conversion if needed. + fn read_path_from_wide_str(&self, scalar: Scalar) -> InterpResult<'tcx, PathBuf> { + 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, false))) } - /// Write a Path to the machine memory, adjusting path separators if needed. + /// Write a Path to the machine memory (as a null-terminated sequence of bytes), + /// adjusting path separators if needed. fn write_path_to_c_str( &mut self, path: &Path, @@ -214,35 +202,57 @@ fn write_path_to_c_str( size: u64, ) -> InterpResult<'tcx, (bool, u64)> { let this = self.eval_context_mut(); - - #[cfg(windows)] - let os_str = if this.tcx.sess.target.target.target_os == "windows" { - // Windows-on-Windows, all fine. - Cow::Borrowed(path.as_os_str()) - } else { - // Unix target, Windows host. Need to convert host '\\' to target '/'. - let converted = path - .as_os_str() - .encode_wide() - .map(|wchar| if wchar == '\\' as u16 { '/' as u16 } else { wchar }) - .collect::>(); - Cow::Owned(OsString::from_wide(&converted)) - }; - #[cfg(unix)] - let os_str = if this.tcx.sess.target.target.target_os == "windows" { - // Windows target, Unix host. Need to convert host '/' to target '\'. - let converted = path - .as_os_str() - .as_bytes() - .iter() - .map(|&wchar| if wchar == '/' as u8 { '\\' as u8 } else { wchar }) - .collect::>(); - Cow::Owned(OsString::from_vec(converted)) - } else { - // Unix-on-Unix, all is fine. - Cow::Borrowed(path.as_os_str()) - }; - + 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) } + + /// Write a Path to the machine memory (as a null-terminated sequence of `u16`s), + /// adjusting path separators if needed. + fn write_path_to_wide_str( + &mut self, + path: &Path, + scalar: Scalar, + 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, 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. + let (from, to) = if direction { ('\\', '/') } else { ('/', '\\') }; + let converted = os_str + .encode_wide() + .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. + let (from, to) = if direction { ('/', '\\') } else { ('\\', '/') }; + let converted = os_str + .as_bytes() + .iter() + .map(|&wchar| if wchar == from as u8 { to as u8 } else { wchar }) + .collect::>(); + Cow::Owned(OsString::from_vec(converted)) + } else { + // Unix-on-Unix, all is fine. + Cow::Borrowed(os_str) + }; }