small refactorings to 'src/shims/os_str.rs' & 'src/shims/env.rs'
This commit is contained in:
parent
1667ded0d2
commit
1b0abc5797
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user