You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
<filesystem>: lexically_relative() can not handle long path with prefix \\?\ #2256
Describe the bug
I would expect that this line of code is true: std::filesystem::path("\\\\?\\C:\\a\\d").lexically_relative("\\\\?\\C:\\a") == "d"
But it is not, because an empty string will be returned. The reason for that is, that inside of lexically_relative() a check _Relative_path_contains_root_name() will be executed, but this is always true. The reason is how the filesystem is handling the root name as explained in _Find_root_name_end(). There is pointed out, that in my case \\?\ is the root name. But at the same time, the path contains C:\ which is a valid root name as well. Because of that, we have the weird behaving, that: std::filesystem::path("\\\\?\\C:\\a\\d").relative_path() == "C:\\a\\d") which is not a relative path and causes the misbehaving of lexically_relative, because it can find another root_name inside of the "relative" path.
Expected behavior
That \\?\C:\ will be treated as root path and not \\?\
STL version
16.11.3
Additional context
In another issue #1921 StephanTLavavej pointed out, that \\?\ only should be used by expert users and I agree. But in case I want to use the new Desktop-Bridge I had to use the new manifest appxmanifest, which not has a property anymore longPathAware. So I don't know how my app gives the consence of supporting that. (Is there maybe a better way to opt-in to the long path app wise) And I don't find any documentation for this use case, besides https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd. And so my only solution to solve this issue is, of converting the paths with the prefix \\?\. But this from my point of view is not well handled by the std::filesystem lib.
Unfortunately, I don't believe this is fixable in our implementation, at least as the standard is currently specified (see [fs.path.gen]/3.4). I may personally agree that \\?\C: should be treated as the root-name here, but that is not the implementation that we chose and it would be a pretty major silent breaking change to change that now.
Due to this, I believe that this should be opened as a WG21 issue?
I think it is too late to change root_name() but agree we should have parsed \\?\c: as root-name if I had a time machine. It does make analysis more complicated, for example, \\?\c:bar is not a relative path, it is just broken. I think I was thinking "\\?\ is an explicit opt-in to everything-like-posix-paths-semantics" (because that is how the NT namespace behaves) when designing this.
For your immediate bug/issue, I think a special case inside lexically_relative for \\?\ is probably reasonable to do... crystalizing into standardese that makes sense everywhere won't be so easy but I don't think we need to wait for an accepted resolution to fix it as long as the LWG issue is actually filed.
The output:
root name
absolute: w:?\C: \temp\test-file.txt
root directory \
root_path \
relative_path ?\C:\temp\test-file.txt
parent_path \?\C:\temp
The “root name” component extracted from the path is reported as an empty string (””). However, the expected value was “C:”, which represents the drive letter of the path.
The root directory output is "\", however it should be "C:\".
What is the reason for this behavior of std::filesystem::path?
Activity
strega-nil-ms commentedon May 12, 2022
Unfortunately, I don't believe this is fixable in our implementation, at least as the standard is currently specified (see [fs.path.gen]/3.4). I may personally agree that
\\?\C:should be treated as the root-name here, but that is not the implementation that we chose and it would be a pretty major silent breaking change to change that now.Due to this, I believe that this should be opened as a WG21 issue?
BillyONeal commentedon May 12, 2022
Related: LWG-3070
I think it is too late to change
root_name()but agree we should have parsed\\?\c:as root-name if I had a time machine. It does make analysis more complicated, for example,\\?\c:baris not a relative path, it is just broken. I think I was thinking "\\?\is an explicit opt-in to everything-like-posix-paths-semantics" (because that is how the NT namespace behaves) when designing this.For your immediate bug/issue, I think a special case inside
lexically_relativefor\\?\is probably reasonable to do... crystalizing into standardese that makes sense everywhere won't be so easy but I don't think we need to wait for an accepted resolution to fix it as long as the LWG issue is actually filed.Thanks for the bug report!
strega-nil-ms commentedon May 13, 2022
I have submitted a WG21 issue, tho it has not been officially opened. I'll update when that's done.
strega-nil commentedon May 23, 2022
WG21 issue here: https://cplusplus.github.io/LWG/issue3699
ZubairRafiq commentedon Jun 17, 2023
The output:
root name
absolute: w:?\C: \temp\test-file.txt
root directory
\root_path
\relative_path ?\C:\temp\test-file.txt
parent_path \?\C:\temp
The “root name” component extracted from the path is reported as an empty string (
””). However, the expected value was “C:”, which represents the drive letter of the path.The root directory output is
"\", however it should be"C:\".What is the reason for this behavior of std::filesystem::path?