-
Notifications
You must be signed in to change notification settings - Fork 356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows shims for GetCurrentDirectoryW/SetCurrentDirectoryW #1268
Conversation
Thanks! But what about the plan to move the string helper functions to their own file? |
I realized today that implementing shims for |
I mean I don't have strong opinions about the order, I just feel cleanup PRs should be done before new features. And this one here adds even more string helpers, so the earlier we do this the better. |
@bors try |
Windows shims for GetCurrentDirectoryW/SetCurrentDirectoryW Implemented shims for Windows * [GetCurrentDirectoryW](https://github.com/rust-lang/rust/blob/75208942f6144daac669e8e382029fc33bdce841/src/libstd/sys/windows/os.rs#L242) (`getcwd` for Windows) * [SetCurrentDirectoryW](https://github.com/rust-lang/rust/blob/75208942f6144daac669e8e382029fc33bdce841/src/libstd/sys/windows/os.rs#L250) (`chdir` for Windows) Currently passes test : `./miri run tests/run-pass/current_dir.rs -Zmiri-disable-isolation`
☀️ Try build successful - checks-travis, status-appveyor |
In that case, I'll submit a new PR to move the string helper functions to |
Thanks! :) |
src/helpers.rs
Outdated
@@ -428,11 +435,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx | |||
} | |||
})? | |||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please only enter this branch if the target_os
is really "windows"
src/helpers.rs
Outdated
"setting the last OS error from an io::Error is yet unsupported for {}.", | ||
target.target_os |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error makes no sense here: the target OS is fine (it's Windows), but the error is the issue. So the error should be like io error {} cannot be transformed into a raw os error
above.
src/shims/env.rs
Outdated
let len = this.write_path_to_wide_str(&cwd, buf, size)?.1; | ||
return Ok(u32::try_from(len).unwrap()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entirely ignores whether the buffer was big enough to hold the string (.0
component of what write_path_to_wide_str
returns). Is that how Windows operates?
The docs say
If the buffer that is pointed to by lpBuffer is not large enough, the return value specifies the required size of the buffer, in characters, including the null-terminating character.
which is not what the function here does. This is the same as the "get env var" shim, so it is worth factoring out the common code into a (local, for now) helper function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll fix this in the upcoming commit
src/shims/env.rs
Outdated
fn SetCurrentDirectoryW ( | ||
&mut self, | ||
path_op: OpTy<'tcx, Tag> // LPCTSTR | ||
) -> InterpResult<'tcx, i32> { // Returns BOOL(i32 in Windows) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
) -> InterpResult<'tcx, i32> { // Returns BOOL(i32 in Windows) | |
) -> InterpResult<'tcx, i32> { // Returns BOOL (i32 in Windows) |
src/shims/os_str.rs
Outdated
/// if direction == true, Convert from 'host' to 'target'. | ||
/// if direction == false, Convert from 'target' to 'host'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, don't use magic booleans. On the call site it is impossible to say what they mean.
Introduce an enum
with appropriately named variants instead.
src/shims/os_str.rs
Outdated
) -> 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 { ('/', '\\') }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea to unify the two directions into one function. :)
1. Fix 'fn convert_path_separator' in src/shims/os_str.rs 2. Fix 'fn set_last_error_from_io_error' in src/helpers.rs 3. Minor comment fix for 'fn SetCurrentDirectoryW' in src/shims/env.rs
I made a force-push to rebase to master |
src/shims/os_str.rs
Outdated
} | ||
} | ||
|
||
enum PathConversionDirection { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. :D
If you want things slightly less verbose, PathConversion
also does it.
Please add a doc comment explaining the purpose of this type.
This looks great, thanks a lot. :) |
📌 Commit 9bdb4bb has been approved by |
let this = self.eval_context_ref(); | ||
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, Pathconversion::TargetToHost))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This performs an unnecessary allocation when host and target are the same: you have a PathBuf
, but just borrow it to convert_path_separator
, which returns a Cow::Borrowed
, which then PathBuf::from
turns into a Cow::Owned
by making a full copy.
To avoid that unnecessary copy, convert_path_separator
should take a Cow<'a, OsStr>
as argument. In a follow-up PR, do you want to fix that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please correct me if I'm wrong:
Type of os_str
here is OsString
(read_os_str_from_wide_str
returns OsString
, unlike read_os_str_from_c_str
).
So I thought borrowing would not be possible, since os_str
would be deallocated after control flow exits the function's local scope.
If avoiding a copy is possible here, I can work on that in a follow-up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are doing &os_str
. That is borrowing.
If you use Cow
, os_str
will instead be moved to convert_path_separator
, and this not deallocated. Then its memory can be reused when the same Cow
is returned later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the clarification.
I'll try to fix that in a separate PR ( probably tomorrow :) )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made a new pr to handle this issue here
☀️ Test successful - checks-travis, status-appveyor |
Implemented shims for Windows
getcwd
for Windows)chdir
for Windows)Currently passes test :
./miri run tests/run-pass/current_dir.rs -Zmiri-disable-isolation