Skip to content

Commit 5f187e5

Browse files
committed
[libc++] Fix filesystem::remove_all() on FreeBSD
remove_all_impl() opens the target path with O_NOFOLLOW, which fails if the target is a symbolic link. On FreeBSD, rather than returning ELOOP, openat() returns EMLINK. This is unlikely to change for compatibility reasons, see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=214633 . Thus, check for EMLINK as well.
1 parent 67c1c1d commit 5f187e5

File tree

1 file changed

+3
-2
lines changed

1 file changed

+3
-2
lines changed

libcxx/src/filesystem/operations.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,8 +815,9 @@ uintmax_t remove_all_impl(int parent_directory, const path& p, error_code& ec) {
815815

816816
// If opening `p` failed because it wasn't a directory, remove it as
817817
// a normal file instead. Note that `openat()` can return either ENOTDIR
818-
// or ELOOP depending on the exact reason of the failure.
819-
if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels) {
818+
// or ELOOP depending on the exact reason of the failure. On FreeBSD it
819+
// may return EMLINK instead of ELOOP, contradicting POSIX.
820+
if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels || ec == errc::too_many_links) {
820821
ec.clear();
821822
if (::unlinkat(parent_directory, p.c_str(), /* flags = */ 0) == -1) {
822823
ec = detail::capture_errno();

0 commit comments

Comments
 (0)