From ee14a9725d73150e89367550206803fe36ae3089 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 29 Jan 2024 18:26:48 +0100 Subject: [PATCH] Merge commit 4a39d0890894 from llvm-project (by Mark Johnston): [libc++] Fix filesystem::remove_all() on FreeBSD (#79540) 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. Reported by: markj PR: 276632 MFC after: 3 days --- contrib/llvm-project/libcxx/src/filesystem/operations.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/llvm-project/libcxx/src/filesystem/operations.cpp b/contrib/llvm-project/libcxx/src/filesystem/operations.cpp index 63a119aa983e..1877bcd79f4d 100644 --- a/contrib/llvm-project/libcxx/src/filesystem/operations.cpp +++ b/contrib/llvm-project/libcxx/src/filesystem/operations.cpp @@ -823,8 +823,9 @@ uintmax_t remove_all_impl(int parent_directory, const path& p, error_code& ec) { // If opening `p` failed because it wasn't a directory, remove it as // a normal file instead. Note that `openat()` can return either ENOTDIR - // or ELOOP depending on the exact reason of the failure. - if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels) { + // or ELOOP depending on the exact reason of the failure. On FreeBSD it + // may return EMLINK instead of ELOOP, contradicting POSIX. + if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels || ec == errc::too_many_links) { ec.clear(); if (::unlinkat(parent_directory, p.c_str(), /* flags = */0) == -1) { ec = detail::capture_errno();