diff --git a/text/0000-long-paths-windows.md b/text/0000-long-paths-windows.md new file mode 100644 index 00000000000..7eafb84ec7d --- /dev/null +++ b/text/0000-long-paths-windows.md @@ -0,0 +1,45 @@ +- Feature Name: long_windows_paths +- Start Date: 2017-10-24 +- RFC PR: +- Rust Issue: + +# Summary +[summary]: #summary + +Rust programs currently cannot access files on Windows 8 and below with paths longer than `MAX_PATH`. This is a bug and should be fixed. + +# Motivation +[motivation]: #motivation + +Windows 8 and below make it difficult but not impossible for a program to access a file with a name longer than `MAX_PATH`. The kernel APIs have no problem with such paths at all, but the user-mode APIs do. They require that the path be prefixed with `\\?\`, which disables all normalization. + +Fortunately, there is a solution that gets back normalization: if (and only if) the file name *does not* begin with `\??\` or `\\?\`, one can pass it to the Windows API function `GetFullPathNameW`, which supports long paths just fine and can easily be called from Rust. The resulting path can safely have `\\?\` prepended and then be passed to the underlying Windows API calls.  `GetFullPathNameW`’s documentation claims that it does not support long paths, but it in fact does. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +This should require at most a brief mention in the Rust book. All that is needed is a note that while many programs do not support long paths on Windows 8 and below (or Windows 10 without proper manifest/registry settings), Rust’s standard library has no such problems, and will work on any path that the underlying NT API supports. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +Whenever Rust sends a path to an underlying NT API, it should use first check if the path length is less than 260 characters **or** begins with either `\\?\` or `\??\`, then pass it to the underlying Windows API function directly. Otherwise, pass it to `GetFullPathNameW`. If it fails, return; if not, pass the result to the underlying Windows API call. + +# Drawbacks +[drawbacks]: #drawbacks + +This adds a small amount of complexity to the standard library. This complexity should be more than compensated by the ability to handle long paths generated by e.g. NPM. + +# Rationale and alternatives +[alternatives]: #alternatives + +The alternatives are: + +- Do nothing. This is bad, because tools like NPM already support and generate long paths. +- Try to implement `GetFullPathNameW` in pure Rust. This is not easy, and does not guarantee compatibility with the Windows implementation. +- Use `GetFullPathNameW` to allow for long paths on Windows. This is the approach chosen here. + +# Unresolved questions +[unresolved]: #unresolved-questions + +None. This is a bug fix, pure and simple.