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.
This commit is contained in:
Paul Eggert
2023-07-22 13:39:17 -07:00
parent b0e41e3f30
commit 3cb862ce5f
3 changed files with 25 additions and 4 deletions

7
NEWS
View File

@@ -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

View File

@@ -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;
}

View File

@@ -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