`<filesystem>`: `directory_entry{}` should throw `std::errc::filename_too_long` if the filename is longer than the limit
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 11.1k
- Forks
- 1.7k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 22
Description
Describe the bug
Environment: with Long Paths DISABLED. Yuck. But test will probably still work due to lack of longPathAware manifest.
__std_fs_get_stats calls GetFileAttributesExW() on a filename that exists, but is too long,
this function returns that it does not exist, and that is the result.
However, if the parent path is UNDER the limit by a few characters, and the filename is OVER the limit,
then you can use directory_iterator{parent_dir} to retrieve the details of the filename (and will say it exists),
but, if you call directory_entry{filename}, it will tell you the file does not exist.
Instead, if the filename is too long because of the legacy limits, then please, throw the exception. Don't say the query was successful and the file does not exist.
It is problematic that directory_iterator will still work, but, whatever, this is still better.
Command-line test case
C:\Temp>type test_stat_long.cpp
#include <iostream>
#include <filesystem>
#include <fstream>
int main()
{
try {
std::filesystem::path short_base_folder { "c:/Temp/short" };
std::filesystem::path long_base_folder { "c:/Temp/long long long long long long long long long" };
std::filesystem::path subfolders { "long long long long long long/long long long long long long/long long long long long long/long long long long long long/long long long long long long/long long long long long long/final long" };
std::filesystem::path short_folder { short_base_folder / subfolders };
std::filesystem::path long_folder { long_base_folder / subfolders };
std::filesystem::create_directories(short_folder);
std::filesystem::path fn { "long_long_file_name_the_file.txt" };
std::filesystem::path fn_short_path = short_folder / fn;
std::filesystem::path fn_long_path = long_folder / fn;
std::ofstream out;
out.exceptions(std::ios::badbit | std::ios::failbit);
out.open(fn_short_path, std::ios::binary);
out << "Hello world\n";
out.close();
std::filesystem::rename(short_base_folder, long_base_folder);
for ( std::filesystem::directory_entry entry : std::filesystem::directory_iterator { long_folder } )
std::cout << "Iterator, file: " << entry.path().generic_string() << "\nFile exists? " << (int)entry.exists() << std::endl << std::endl;
std::filesystem::directory_entry entry { fn_long_path };
std::cout << "Direct: File exists? " << (int)entry.exists() << std::endl;
return 0;
}
catch (std::exception & e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
catch (...) {
std::cerr << "Unknown Exception" << std::endl;
}
return 1;
}
C:\Temp>cl /EHsc /W4 /WX /std:c++latest .\test_stat_long.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.43.34810 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
/std:c++latest is provided as a preview of language features from the latest C++
working draft, and we're eager to hear about bugs and suggestions for improvements.
However, note that these features are provided as-is without support, and subject
to changes or removal as the working draft evolves. See
https://go.microsoft.com/fwlink/?linkid=2045807 for details.
test_stat_long.cpp
Microsoft (R) Incremental Linker Version 14.43.34810.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:test_stat_long.exe
test_stat_long.obj
C:\Temp>.\test_stat_long.exe
Iterator, file: c:/Temp/long long long long long long long long long/long long long long long long/long long long long long long/long long long long long long/long long long long long long/long long long long long long/long long long long long long/final long/long_long_file_name_the_file.txt
File exists? 1
Direct: File exists? 0
Expected behavior
If long-paths were enabled in the registry, and the program had a manifest for longPathAware=true,
then I would expect "File exists? 1".
In this case, with long-paths disabled and no program manifest,
I would expect directory_entry to throw a filesystem_error(filename_too_long)
STL version
- Visual Studio version
Microsoft Visual Studio Community 2022 (64-bit) - Current
Version 17.13.6
```
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at stl/src/filesystem.cpp around line 868, where __std_fs_get_stats calls GetFileAttributesExW(), and reproduce the supplied test on Windows with long paths disabled. Done means direct construction of directory_entry for an over-limit filename reports filesystem_error with std::errc::filename_too_long instead of treating the path as nonexistent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 38/100