bug#78245: rm -d fails to remove non-empty directory

Paul Eggert <[email protected]>
Newsgroups gmane.comp.gnu.core-utils.bugs
Organization UCLA Computer Science Department
Message-ID <[email protected]>
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.
0001-rm-make-rm-d-DIR-more-like-rmdir-DIR.patch (text/x-patch, 2.6 KB)
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
0002-rm-remove-redundant-mark_ancestor_dirs-call.patch (text/x-patch, 877 B)
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.