fix wrong error msg of save command on windows (#14699)

fixes #14664 

# Description

Now,

```nu
"aaa" | save -f ..
```

returns correct error message on windows.

Note that the fix introduces a TOCTOU problem, which only effects the
error message. It won't break any workload.

# User-Facing Changes

The fix won't break any workload.

# Tests + Formatting

I have run tests **only on windows**.

# After Submitting

The fix doesn't need to change documentation.
This commit is contained in:
Chen1Plus 2025-01-07 07:36:42 +08:00 committed by GitHub
parent 9ed2ca792f
commit ac12b02437
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 25 additions and 1 deletions

View File

@ -422,7 +422,22 @@ fn prepare_path(
fn open_file(path: &Path, span: Span, append: bool) -> Result<File, ShellError> {
let file = match (append, path.exists()) {
(true, true) => std::fs::OpenOptions::new().append(true).open(path),
_ => std::fs::File::create(path),
_ => {
// This is a temporary solution until `std::fs::File::create` is fixed on Windows (rust-lang/rust#134893)
// A TOCTOU problem exists here, which may cause wrong error message to be shown
#[cfg(target_os = "windows")]
if path.is_dir() {
// It should be `io::ErrorKind::IsADirectory` but it's not available in stable yet (1.83)
Err(io::Error::new(
io::ErrorKind::Unsupported,
"Is a directory (os error 21)",
))
} else {
std::fs::File::create(path)
}
#[cfg(not(target_os = "windows"))]
std::fs::File::create(path)
}
};
file.map_err(|e| ShellError::GenericError {

View File

@ -525,3 +525,12 @@ fn parent_redirection_doesnt_affect_save() {
assert_eq!(actual.trim_end(), "");
})
}
#[test]
fn force_save_to_dir() {
let actual = nu!(cwd: "crates/nu-command/tests/commands", r#"
"aaa" | save -f ..
"#);
assert!(actual.err.contains("Is a directory"));
}