mirror of
git://git.sv.gnu.org/coreutils
synced 2026-06-04 14:55:00 -04:00
(copy_internal): Be consistent with intra-device behavior
and *do* allow `mv' to move a file onto a symlink to itself when that symlink is on a separate partition. With fileutils-4.0j, it would fail with a diagnostic saying they were the same file. Reported by Bruno Haible.
This commit is contained in:
+31
-12
@@ -371,6 +371,7 @@ copy_internal (const char *src_path, const char *dst_path,
|
||||
char *earlier_file;
|
||||
char *dst_backup = NULL;
|
||||
int fix_mode = 0;
|
||||
int force = x->force;
|
||||
|
||||
if (move_mode && rename_succeeded)
|
||||
*rename_succeeded = 0;
|
||||
@@ -426,14 +427,7 @@ copy_internal (const char *src_path, const char *dst_path,
|
||||
if (!same
|
||||
|
||||
/* If we'll remove DST_PATH first, then this doesn't matter. */
|
||||
&& ! x->force
|
||||
|
||||
/* Allow them to be the same (and don't set `same') if
|
||||
we're in move mode and the target is a symlink
|
||||
on the same partition. */
|
||||
&& !(move_mode
|
||||
&& S_ISLNK (dst_sb.st_mode)
|
||||
&& src_sb.st_dev == dst_sb.st_dev)
|
||||
&& ! force
|
||||
|
||||
/* If we're making a backup, we'll detect the problem case in
|
||||
copy_reg because SRC_PATH will no longer exist. Allowing
|
||||
@@ -453,7 +447,32 @@ copy_internal (const char *src_path, const char *dst_path,
|
||||
&& stat (src_path, &src2_sb) == 0
|
||||
&& SAME_INODE (src2_sb, dst2_sb))
|
||||
{
|
||||
same = 1;
|
||||
/* Be careful in move mode when the target is a symlink
|
||||
to the source. */
|
||||
if (move_mode
|
||||
&& S_ISLNK (dst_sb.st_mode))
|
||||
{
|
||||
if (src_sb.st_dev != dst_sb.st_dev)
|
||||
{
|
||||
/* This happens when the target is a symlink that
|
||||
resides on a file system different from the one
|
||||
on which the source resides. Tell the copying
|
||||
code (below) that it must unlink the destination
|
||||
before opening it. Otherwise, we'd end up
|
||||
destroying SRC when opening it via the symlink. */
|
||||
force = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't set `same'.
|
||||
Since they're on the same partition, rename
|
||||
will end up removing the destination symlink. */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
same = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -464,7 +483,7 @@ copy_internal (const char *src_path, const char *dst_path,
|
||||
return 0;
|
||||
|
||||
if (x->backup_type == none
|
||||
&& (!x->force || same_name (src_path, dst_path)))
|
||||
&& (!force || same_name (src_path, dst_path)))
|
||||
{
|
||||
error (0, 0, _("`%s' and `%s' are the same file"),
|
||||
src_path, dst_path);
|
||||
@@ -486,7 +505,7 @@ copy_internal (const char *src_path, const char *dst_path,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISDIR (src_type) && !x->force && x->interactive)
|
||||
if (!S_ISDIR (src_type) && !force && x->interactive)
|
||||
{
|
||||
if (euidaccess (dst_path, W_OK) != 0)
|
||||
{
|
||||
@@ -554,7 +573,7 @@ copy_internal (const char *src_path, const char *dst_path,
|
||||
}
|
||||
new_dst = 1;
|
||||
}
|
||||
else if (x->force)
|
||||
else if (force)
|
||||
{
|
||||
if (S_ISDIR (dst_sb.st_mode))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user