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

File::create fails on hidden files on Windows #115745

Closed
ChrisDenton opened this issue Sep 11, 2023 · 3 comments · Fixed by #116438
Closed

File::create fails on hidden files on Windows #115745

ChrisDenton opened this issue Sep 11, 2023 · 3 comments · Fixed by #116438
Labels
A-io Area: `std::io`, `std::fs`, `std::net` and `std::path` C-bug Category: This is a bug. O-windows Operating system: Windows T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@ChrisDenton
Copy link
Member

Reported on discord, using OpenOptions::new().write(true).create(true).truncate(true).open(&path) will fail on Windows if the file is hidden. This also affects methods like File::create or fs::write that open the file the same way.

The reason for this is that we use CREATE_ALWAYS, which has strange behaviour:

If CREATE_ALWAYS and FILE_ATTRIBUTE_NORMAL are specified, CreateFile fails and sets the last error to ERROR_ACCESS_DENIED if the file exists and has the FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM attribute. To avoid the error, specify the same attributes as the existing file.

So to make it work the caller needs to match the requested attributes to the existing attributes at the time of opening.

Possible solution

It was suggested we could instead use OPEN_ALWAYS and then manually truncate the file using SetFileInformationByHandle to set the FILE_ALLOCATION_INFO to zero.

@ChrisDenton ChrisDenton added O-windows Operating system: Windows C-bug Category: This is a bug. T-libs Relevant to the library team, which will review and decide on the PR/issue. A-io Area: `std::io`, `std::fs`, `std::net` and `std::path` labels Sep 11, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Sep 11, 2023
@ChrisDenton ChrisDenton removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Sep 11, 2023
@bjorn3
Copy link
Member

bjorn3 commented Sep 11, 2023

Manually truncating would require also clearing the alternate data streams too, right? And it would presumably stop erroring if another process still has the file open and instead corrupt the file fron the view of the other process.

@ChrisDenton
Copy link
Member Author

No? The proposed solution would work the same was as TRUNCATE_EXISTING in the case where the file already exists. Which we use for .write(true).truncate(true).

@bjorn3
Copy link
Member

bjorn3 commented Sep 12, 2023

Right, got confused with create_new.

bors added a commit to rust-lang-ci/rust that referenced this issue Oct 24, 2023
Windows: Allow `File::create` to work on hidden files

This makes `OpenOptions::new().write(true).create(true).truncate(true).open(&path)` work if the path exists and is a hidden file. Previously it would fail with access denied.

This makes it consistent with `OpenOptions::new().write(true).truncate(true).open(&path)` (note the lack of `create`) which does not have this restriction. It's also more consistent with other platforms.

Fixes rust-lang#115745 (see that issue for more details).
TaKO8Ki added a commit to TaKO8Ki/rust that referenced this issue Nov 9, 2023
Windows: Allow `File::create` to work on hidden files

This makes `OpenOptions::new().write(true).create(true).truncate(true).open(&path)` work if the path exists and is a hidden file. Previously it would fail with access denied.

This makes it consistent with `OpenOptions::new().write(true).truncate(true).open(&path)` (note the lack of `create`) which does not have this restriction. It's also more consistent with other platforms.

Fixes rust-lang#115745 (see that issue for more details).
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Dec 8, 2023
Windows: Allow `File::create` to work on hidden files

This makes `OpenOptions::new().write(true).create(true).truncate(true).open(&path)` work if the path exists and is a hidden file. Previously it would fail with access denied.

This makes it consistent with `OpenOptions::new().write(true).truncate(true).open(&path)` (note the lack of `create`) which does not have this restriction. It's also more consistent with other platforms.

Fixes rust-lang#115745 (see that issue for more details).
bors added a commit to rust-lang-ci/rust that referenced this issue Dec 9, 2023
Windows: Allow `File::create` to work on hidden files

This makes `OpenOptions::new().write(true).create(true).truncate(true).open(&path)` work if the path exists and is a hidden file. Previously it would fail with access denied.

This makes it consistent with `OpenOptions::new().write(true).truncate(true).open(&path)` (note the lack of `create`) which does not have this restriction. It's also more consistent with other platforms.

Fixes rust-lang#115745 (see that issue for more details).
@bors bors closed this as completed in 77d1699 Dec 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-io Area: `std::io`, `std::fs`, `std::net` and `std::path` C-bug Category: This is a bug. O-windows Operating system: Windows T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants