Skip to content
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

Merged
merged 7 commits into from
Mar 29, 2020

Conversation

JOE1994
Copy link
Contributor

@JOE1994 JOE1994 commented Mar 27, 2020

Implemented shims for Windows

Currently passes test :
./miri run tests/run-pass/current_dir.rs -Zmiri-disable-isolation

@RalfJung
Copy link
Member

Thanks! But what about the plan to move the string helper functions to their own file?

@JOE1994
Copy link
Contributor Author

JOE1994 commented Mar 28, 2020

Thanks! But what about the plan to move the string helper functions to their own file?

I realized today that implementing shims for current_dir and set_current_dir on Windows was also a part of the plan laid out in #707 (comment). I was thinking of submitting a new PR to move the string helper functions to their own file, once this PR gets merged to master. Would that be okay?

@RalfJung
Copy link
Member

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.

src/helpers.rs Outdated Show resolved Hide resolved
src/helpers.rs Outdated Show resolved Hide resolved
src/shims/env.rs Outdated Show resolved Hide resolved
src/shims/env.rs Outdated Show resolved Hide resolved
@RalfJung
Copy link
Member

@bors try

@bors
Copy link
Contributor

bors commented Mar 28, 2020

⌛ Trying commit dfc4aaf with merge d903aa5...

bors added a commit that referenced this pull request Mar 28, 2020
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`
@bors
Copy link
Contributor

bors commented Mar 28, 2020

☀️ Try build successful - checks-travis, status-appveyor
Build commit: d903aa5 (d903aa5e31afbd50f28bbc624caf209fa5fb43b3)

@JOE1994
Copy link
Contributor Author

JOE1994 commented Mar 28, 2020

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.

In that case, I'll submit a new PR to move the string helper functions to shims/os_str.rs, and then rebase the changes in this PR.

@RalfJung
Copy link
Member

Thanks! :)

src/helpers.rs Outdated
@@ -428,11 +435,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}
})?
} else {
Copy link
Member

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
Comment on lines 442 to 443
"setting the last OS error from an io::Error is yet unsupported for {}.",
target.target_os
Copy link
Member

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
Comment on lines 330 to 331
let len = this.write_path_to_wide_str(&cwd, buf, size)?.1;
return Ok(u32::try_from(len).unwrap())
Copy link
Member

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.

Copy link
Contributor Author

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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
) -> InterpResult<'tcx, i32> { // Returns BOOL(i32 in Windows)
) -> InterpResult<'tcx, i32> { // Returns BOOL (i32 in Windows)

src/shims/os_str.rs Outdated Show resolved Hide resolved
Comment on lines 224 to 225
/// if direction == true, Convert from 'host' to 'target'.
/// if direction == false, Convert from 'target' to 'host'.
Copy link
Member

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.

) -> 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 { ('/', '\\') };
Copy link
Member

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. :)

JOE1994 added 5 commits March 29, 2020 11:30
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
@JOE1994
Copy link
Contributor Author

JOE1994 commented Mar 29, 2020

I made a force-push to rebase to master

src/shims/env.rs Outdated Show resolved Hide resolved
src/shims/os_str.rs Outdated Show resolved Hide resolved
}
}

enum PathConversionDirection {
Copy link
Member

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.

src/shims/os_str.rs Outdated Show resolved Hide resolved
src/shims/env.rs Outdated Show resolved Hide resolved
@RalfJung
Copy link
Member

This looks great, thanks a lot. :)
@bors r+

@bors
Copy link
Contributor

bors commented Mar 29, 2020

📌 Commit 9bdb4bb has been approved by RalfJung

@bors
Copy link
Contributor

bors commented Mar 29, 2020

⌛ Testing commit 9bdb4bb with merge 3504d52...

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)))
Copy link
Member

@RalfJung RalfJung Mar 29, 2020

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?

Copy link
Contributor Author

@JOE1994 JOE1994 Mar 29, 2020

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.

Copy link
Member

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.

Copy link
Contributor Author

@JOE1994 JOE1994 Mar 29, 2020

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 :) )

Copy link
Contributor Author

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

@bors
Copy link
Contributor

bors commented Mar 29, 2020

☀️ Test successful - checks-travis, status-appveyor
Approved by: RalfJung
Pushing 3504d52 to master...

@bors bors merged commit 3504d52 into rust-lang:master Mar 29, 2020
@JOE1994 JOE1994 deleted the dir branch March 29, 2020 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants