Subject: Re: bug#64785: Package: coreutils Version: 8.32-4+b1 program=mv
From: Paul Eggert <[email-masked]>
To: Nir Oren <[email-masked]>
Cc: [email-masked],Pádraig Brady <[email-masked]>
Date: Sat, 22 Jul 2023 13:47:47 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

Thanks to both of you. I installed the attached into Savannah master 
coreutils. It implements the suggestion, except that later I noticed 
that EMLINK and ETXTBSY can join the throng.

At some point it might make sense to scan for other direct or indirect 
calls to renameat, renameat2, and linkat, where the diagnostic could be 
improved if it's known to refer to the destination.

From 3cb862ce5f10db392cc8e6907dd9d888acfa2a30 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sat, 22 Jul 2023 13:39:17 -0700
Subject: [PATCH] mv: better diagnostic for 'mv dir x' failure

Problem reported by Nir Oren <https://bugs.gnu.org/64785>.
* src/copy.c (copy_internal): Use a more-specific diagnostic when
a rename fails due to a problem that must be due to the
destination, avoiding user confusion in cases like 'mv dir x'
where x is a nonempty directory.
* tests/mv/dir2dir.sh: Adjust to match.
---
 NEWS                |  7 +++++++
 src/copy.c          | 20 +++++++++++++++++---
 tests/mv/dir2dir.sh |  2 +-
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/NEWS b/NEWS
index 7d2ca7f6b..bd0c59eb5 100644
--- a/NEWS
+++ b/NEWS
@@ -56,6 +56,13 @@ GNU coreutils NEWS                                    -*- outline -*-
   short option is reserved to better support emulation of the standalone
   checksum utilities with cksum.
 
+  'mv dir x' now complains differently if x/dir is a nonempty directory.
+  Previously it said "mv: cannot move 'dir' to 'x/dir': Directory not empty",
+  where it was unclear whether 'dir' or 'x/dir' was the problem.
+  Now it says "mv: cannot overwrite 'x/dir': Directory not empty".
+  Similarly for other renames where the destination must be the problem.
+  [problem introduced in coreutils-6.0]
+
 ** Improvements
 
   cp, mv, and install now avoid copy_file_range on linux kernels before 5.3
diff --git a/src/copy.c b/src/copy.c
index ddc9eab30..90eebf6bc 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -2840,9 +2840,23 @@ skip:
              If the permissions on the directory containing the source or
              destination file are made too restrictive, the rename will
              fail.  Etc.  */
-          error (0, rename_errno,
-                 _("cannot move %s to %s"),
-                 quoteaf_n (0, src_name), quoteaf_n (1, dst_name));
+          char const *quoted_dst_name = quoteaf_n (1, dst_name);
+          switch (rename_errno)
+            {
+            case EDQUOT: case EEXIST: case EISDIR: case EMLINK:
+            case ENOSPC: case ENOTEMPTY: case ETXTBSY:
+              /* The destination must be the problem.  Don't mention
+                 the source as that is more likely to confuse the user
+                 than be helpful.  */
+              error (0, rename_errno, _("cannot overwrite %s"),
+                     quoted_dst_name);
+              break;
+
+            default:
+              error (0, rename_errno, _("cannot move %s to %s"),
+                     quoteaf_n (0, src_name), quoted_dst_name);
+              break;
+            }
           forget_created (src_sb.st_ino, src_sb.st_dev);
           return false;
         }
diff --git a/tests/mv/dir2dir.sh b/tests/mv/dir2dir.sh
index ea99eca56..da6a518e5 100755
--- a/tests/mv/dir2dir.sh
+++ b/tests/mv/dir2dir.sh
@@ -34,7 +34,7 @@ sed             's/: File exists/: Directory not empty/'<out>o1;mv o1 out
 sed 's/: Device or resource busy/: Directory not empty/'<out>o1;mv o1 out
 
 cat <<\EOF > exp || framework_failure_
-mv: cannot move 'b/t' to 'a/t': Directory not empty
+mv: cannot overwrite 'a/t': Directory not empty
 EOF
 
 compare exp out || fail=1
-- 
2.39.2