[libcxx-commits] [libcxx] 4a39d08 - [libc++] Fix filesystem::remove_all() on FreeBSD (#79540)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jan 29 00:20:01 PST 2024


Author: Mark Johnston
Date: 2024-01-29T09:19:57+01:00
New Revision: 4a39d08908942b2d415db405844cbe4af73e75d4

URL: https://github.com/llvm/llvm-project/commit/4a39d08908942b2d415db405844cbe4af73e75d4
DIFF: https://github.com/llvm/llvm-project/commit/4a39d08908942b2d415db405844cbe4af73e75d4.diff

LOG: [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.

Added: 
    

Modified: 
    libcxx/src/filesystem/operations.cpp
    libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp
index 6253d1551b062ea..62bb248d5eca9b5 100644
--- a/libcxx/src/filesystem/operations.cpp
+++ b/libcxx/src/filesystem/operations.cpp
@@ -815,8 +815,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();

diff  --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp
index eaa8044397ed850..5cdbd0878431652 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp
@@ -6,8 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-// XFAIL: LIBCXX-FREEBSD-FIXME
-
 // UNSUPPORTED: c++03, c++11, c++14
 // UNSUPPORTED: no-filesystem
 // UNSUPPORTED: availability-filesystem-missing


        


More information about the libcxx-commits mailing list