On 2025-05-04 11:01, Pádraig Brady wrote:

For reference this was also reported at:
https://bugs.debian.org/1104300

I installed the attached patches (the second one is merely a minor performance improvement) and am marking the bug as done on debugs.gnu.org. Thanks, Yannick, for reporting it.
From bae32db8fead1134e4ce5804f61ec094cf2cad0b Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Mon, 6 Oct 2025 13:31:48 -0700
Subject: [PATCH 1/2] =?UTF-8?q?rm:=20make=20=E2=80=98rm=20-d=20DIR?=
 =?UTF-8?q?=E2=80=99=20more=20like=20=E2=80=98rmdir=20DIR=E2=80=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* src/remove.c (rm_fts): When not recursive,
arrange for ‘rm -d DIR’ to behave more like ‘rmdir DIR’.
This works better for Ceph snapshot directories.
Problem reported by Yannick Le Pennec (bug#78245).
---
 NEWS         |  4 ++++
 src/remove.c | 18 ++++++++----------
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/NEWS b/NEWS
index 428262deb..d5946ced9 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   for all length adjustable algorithms (blake2b, sha2, sha3).
   [bug introduced in coreutils-9.2]
 
+  'rm -d DIR' no longer fails on Ceph snapshot directories.
+  Although these directories are nonempty, 'rmdir DIR' succeeds on them.
+  [bug introduced in coreutils-8.16]
+
   'tail' outputs the correct number of lines again for non-small -n values.
   Previously it may have output too few lines.
   [bug introduced in coreutils-9.8]
diff --git a/src/remove.c b/src/remove.c
index 079b00fc1..f50276efd 100644
--- a/src/remove.c
+++ b/src/remove.c
@@ -446,18 +446,16 @@ rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
   switch (ent->fts_info)
     {
     case FTS_D:			/* preorder directory */
-      if (! x->recursive
-          && !(x->remove_empty_directories
-               && get_dir_status (fts, ent, &dir_status) != 0))
+      if (!x->recursive)
         {
-          /* This is the first (pre-order) encounter with a directory
-             that we cannot delete.
-             Not recursive, and it's not an empty directory (if we're removing
-             them) so arrange to skip contents.  */
-          int err = x->remove_empty_directories ? ENOTEMPTY : EISDIR;
-          error (0, err, _("cannot remove %s"), quoteaf (ent->fts_path));
+          /* Not recursive, so skip contents, and fail now unless
+             removing empty directories.  */
+          fts_set (fts, ent, FTS_SKIP);
+          if (x->remove_empty_directories)
+            return RM_OK;
+          error (0, EISDIR, _("cannot remove %s"), quoteaf (ent->fts_path));
           mark_ancestor_dirs (ent);
-          fts_skip_tree (fts, ent);
+          ignore_value (fts_read (fts));
           return RM_ERROR;
         }
 
-- 
2.48.1

From 311c04c0596a61761790b1c0a5fa99ec59796e14 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Mon, 6 Oct 2025 13:36:40 -0700
Subject: [PATCH 2/2] rm: remove redundant mark_ancestor_dirs call

* src/remove.c (rm_fts): Remove unnecessary call.  Since this code
is executed only when not recursive, there are no ancestors to mark.
---
 src/remove.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/remove.c b/src/remove.c
index f50276efd..86226b1d3 100644
--- a/src/remove.c
+++ b/src/remove.c
@@ -454,7 +454,6 @@ rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
           if (x->remove_empty_directories)
             return RM_OK;
           error (0, EISDIR, _("cannot remove %s"), quoteaf (ent->fts_path));
-          mark_ancestor_dirs (ent);
           ignore_value (fts_read (fts));
           return RM_ERROR;
         }
-- 
2.48.1

Reply via email to