small refactorings to 'src/shims/os_str.rs' & 'src/shims/env.rs'

This commit is contained in:
JOE1994 2020-03-29 13:10:23 -04:00
parent 1667ded0d2
commit 1b0abc5797
2 changed files with 62 additions and 60 deletions

View File

@ -125,7 +125,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let buf_ptr = this.read_scalar(buf_op)?.not_undef()?;
// `buf_size` represents the size in characters.
let buf_size = u64::from(this.read_scalar(size_op)?.to_u32()?);
HowWasBufferSize(this.write_os_str_to_wide_str(&var, buf_ptr, buf_size)?)
windows_check_buffer_size(this.write_os_str_to_wide_str(&var, buf_ptr, buf_size)?)
}
None => {
let envvar_not_found = this.eval_windows("ERROR_ENVVAR_NOT_FOUND")?;
@ -317,7 +317,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// If we cannot get the current directory, we return 0
match env::current_dir() {
Ok(cwd) =>
return Ok(HowWasBufferSize(this.write_path_to_wide_str(&cwd, buf, size)?)),
return Ok(windows_check_buffer_size(this.write_path_to_wide_str(&cwd, buf, size)?)),
Err(e) => this.set_last_error_from_io_error(e)?,
}
Ok(0)
@ -400,16 +400,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}
}
// Local helper function to be used in Windows shims
#[allow(non_snake_case)]
fn HowWasBufferSize((success, len): (bool, u64)) -> u32 {
/// Check whether an operation that writes to a target buffer was successful.
/// Accordingly select return value.
/// Local helper function to be used in Windows shims.
fn windows_check_buffer_size((success, len): (bool, u64)) -> u32 {
if success {
// If the function succeeds, the return value is the number of characters stored in the buffer pointed to by lpBuffer,
// If the function succeeds, the return value is the number of characters stored in the target buffer,
// not including the terminating null character.
u32::try_from(len).unwrap()
} else {
// If lpBuffer is not large enough to hold the data, the return value is the buffer size, in characters,
// required to hold the string and its terminating null character and the contents of lpBuffer are undefined.
// If the target buffer was not large enough to hold the data, the return value is the buffer size, in characters,
// required to hold the string and its terminating null character.
u32::try_from(len.checked_add(1).unwrap()).unwrap()
}
}

View File

@ -13,6 +13,53 @@ use rustc::ty::layout::LayoutOf;
use crate::*;
/// Represent how path separator conversion should be done.
enum Pathconversion {
HostToTarget,
TargetToHost,
}
/// Perform path separator conversion if needed.
fn convert_path_separator<'a>(
os_str: &'a OsStr,
target_os: &str,
direction: Pathconversion,
) -> 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) = match direction {
Pathconversion::HostToTarget => ('\\', '/'),
Pathconversion::TargetToHost => ('/', '\\'),
};
let converted = os_str
.encode_wide()
.map(|wchar| if wchar == from as u16 { to as u16 } else { wchar })
.collect::<Vec<_>>();
Cow::Owned(OsString::from_wide(&converted))
};
#[cfg(unix)]
return if target_os == "windows" {
// Windows target, Unix host.
let (from, to) = match direction {
Pathconversion::HostToTarget => ('/', '\\'),
Pathconversion::TargetToHost => ('\\', '/'),
};
let converted = os_str
.as_bytes()
.iter()
.map(|&wchar| if wchar == from as u8 { to as u8 } else { wchar })
.collect::<Vec<_>>();
Cow::Owned(OsString::from_vec(converted))
} else {
// Unix-on-Unix, all is fine.
Cow::Borrowed(os_str)
};
}
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
/// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
@ -177,9 +224,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
'mir: 'a,
{
let this = self.eval_context_ref();
let os_str: &'a OsStr = this.read_os_str_from_c_str(scalar)?;
let os_str = this.read_os_str_from_c_str(scalar)?;
Ok(match convert_path_separator(os_str, &this.tcx.sess.target.target.target_os, PathConversionDirection::TargetToHost) {
Ok(match convert_path_separator(os_str, &this.tcx.sess.target.target.target_os, Pathconversion::TargetToHost) {
Cow::Borrowed(x) => Cow::Borrowed(Path::new(x)),
Cow::Owned(y) => Cow::Owned(PathBuf::from(y)),
})
@ -188,9 +235,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
/// Read a null-terminated sequence of `u16`s, and perform path separator conversion if needed.
fn read_path_from_wide_str(&self, scalar: Scalar<Tag>) -> InterpResult<'tcx, PathBuf> {
let this = self.eval_context_ref();
let os_str: OsString = this.read_os_str_from_wide_str(scalar)?;
let os_str = this.read_os_str_from_wide_str(scalar)?;
Ok(PathBuf::from(&convert_path_separator(&os_str, &this.tcx.sess.target.target.target_os, PathConversionDirection::TargetToHost)))
Ok(PathBuf::from(&convert_path_separator(&os_str, &this.tcx.sess.target.target.target_os, Pathconversion::TargetToHost)))
}
/// Write a Path to the machine memory (as a null-terminated sequence of bytes),
@ -202,7 +249,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, PathConversionDirection::HostToTarget);
let os_str = convert_path_separator(path.as_os_str(), &this.tcx.sess.target.target.target_os, Pathconversion::HostToTarget);
this.write_os_str_to_c_str(&os_str, scalar, size)
}
@ -215,53 +262,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, PathConversionDirection::HostToTarget);
let os_str = convert_path_separator(path.as_os_str(), &this.tcx.sess.target.target.target_os, Pathconversion::HostToTarget);
this.write_os_str_to_wide_str(&os_str, scalar, size)
}
}
enum PathConversionDirection {
HostToTarget,
TargetToHost,
}
/// Perform path separator conversion if needed.
fn convert_path_separator<'a>(
os_str: &'a OsStr,
target_os: &str,
direction: PathConversionDirection,
) -> 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) = match direction {
PathConversionDirection::HostToTarget => ('\\', '/'),
PathConversionDirection::TargetToHost => ('/', '\\'),
};
let converted = os_str
.encode_wide()
.map(|wchar| if wchar == from as u16 { to as u16 } else { wchar })
.collect::<Vec<_>>();
Cow::Owned(OsString::from_wide(&converted))
};
#[cfg(unix)]
return if target_os == "windows" {
// Windows target, Unix host.
let (from, to) = match direction {
PathConversionDirection::HostToTarget => ('/', '\\'),
PathConversionDirection::TargetToHost => ('\\', '/'),
};
let converted = os_str
.as_bytes()
.iter()
.map(|&wchar| if wchar == from as u8 { to as u8 } else { wchar })
.collect::<Vec<_>>();
Cow::Owned(OsString::from_vec(converted))
} else {
// Unix-on-Unix, all is fine.
Cow::Borrowed(os_str)
};
}