public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] libstdc++: Handle EMLINK and EFTYPE in std::filesystem::remove_all
@ 2024-04-10 15:23 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2024-04-10 15:23 UTC (permalink / raw)
  To: libstdc++, gcc-patches

Tested x86_64-linux and x86_64-freebsd14. Pushed to trunk.

-- >8 --

Although POSIX requires ELOOP, FreeBSD documents that openat with
O_NOFOLLOW returns EMLINK if the last component of a filename is a
symbolic link.  Check for EMLINK as well as ELOOP, so that the TOCTTOU
mitigation in remove_all works correctly.

See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=214633 or the
FreeBSD man page for reference.

According to its man page, DragonFlyBSD also uses EMLINK for this error,
and NetBSD uses its own EFTYPE. OpenBSD follows POSIX and uses EMLINK.

This fixes these failures on FreeBSD:
FAIL: 27_io/filesystem/operations/remove_all.cc  -std=gnu++17 execution test
FAIL: experimental/filesystem/operations/remove_all.cc  -std=gnu++17 execution test

libstdc++-v3/ChangeLog:

	* src/c++17/fs_ops.cc (remove_all) [__FreeBSD__ || __DragonFly__]:
	Check for EMLINK as well as ELOOP.
	[__NetBSD__]: Check for EFTYPE as well as ELOOP.
---
 libstdc++-v3/src/c++17/fs_ops.cc | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 61df19753ef..07bc2a0fa88 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1312,7 +1312,13 @@ fs::remove_all(const path& p)
     // Our work here is done.
     return 0;
   case ENOTDIR:
-  case ELOOP:
+  case ELOOP:  // POSIX says openat with O_NOFOLLOW sets ELOOP for a symlink.
+#if defined __FreeBSD__ || defined __DragonFly__
+  case EMLINK: // Used instead of ELOOP
+#endif
+#if defined __NetBSD__ && defined EFTYPE
+  case EFTYPE: // Used instead of ELOOP
+#endif
     // Not a directory, will remove below.
     break;
 #endif
@@ -1352,7 +1358,13 @@ fs::remove_all(const path& p, error_code& ec)
     ec.clear();
     return 0;
   case ENOTDIR:
-  case ELOOP:
+  case ELOOP:  // POSIX says openat with O_NOFOLLOW sets ELOOP for a symlink.
+#if defined __FreeBSD__ || defined __DragonFly__
+  case EMLINK: // Used instead of ELOOP
+#endif
+#if defined __NetBSD__ && defined EFTYPE
+  case EFTYPE: // Used instead of ELOOP
+#endif
     // Not a directory, will remove below.
     break;
 #endif
-- 
2.44.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-04-10 15:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-10 15:23 [committed] libstdc++: Handle EMLINK and EFTYPE in std::filesystem::remove_all Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).