libstdc++: Fix directory removal for old systems lacking unlinkat
Ensures `std::filesystem::remove_all` correctly removes non-empty directories on systems without `unlinkat`.
On systems lacking unlinkat or dirent::d_type, libstdc++’s directory traversal could fail to correctly identify file types. When __erase was called for a non-empty directory, it would use ::remove which retries as rmdir. If rmdir failed due to the directory not being empty, the error was not handled correctly, leading remove_all to report a failure. This commit adjusts the error handling to accept ENOTEMPTY or EEXIST as valid failure reasons for rmdir in this specific scenario, allowing the operation to proceed.
In Details
The recursive_directory_iterator::__erase function uses fs::remove (which typically calls ::remove or ::unlink) to remove directory entries. On systems without unlinkat or dirent::d_type, _Dir::advance can leave file_type as none. This leads __erase to call _Dir::do_unlink. If do_unlink is called on a directory and unlinkat is unavailable, it falls back to ::remove. If ::remove calls rmdir and fails with ENOTEMPTY, the existing error handling incorrectly propagates this failure. This change modifies the error handling in __erase to treat ENOTEMPTY and `EE…
- unlinkat
- A system call that allows unlinking a file relative to a directory file descriptor, providing more control and security than the traditional
unlink. - dirent::d_type
- A field in the
direntstructure that indicates the type of the file (e.g., directory, regular file) directly from the directory entry, avoiding an extrastatsystem call. - fs::remove
- A C++ standard library function (in
<filesystem>) that removes a file or directory. It often delegates to the underlying operating system'sremoveorunlinksystem calls. - rmdir
- A system call to remove an empty directory.
- ENOTEMPTY
- An error code indicating that a directory is not empty and cannot be removed.
- EEXIST
- An error code indicating that a file or directory already exists.