summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/copy.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/copy.c b/src/copy.c
index 8685234e5..51c5f6db8 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -1099,6 +1099,15 @@ copy_internal (const char *src_path, const char *dst_path,
Sometimes, when preserving links, we have to record dev/ino even
though st_nlink == 1:
+ - when in move_mode, since we may be moving a group of N hard-linked
+ files (via two or more command line arguments) to a different
+ partition; the links may be distributed among the command line
+ arguments (possibly hierarchies) so that the link count of
+ the final, once-linked source file is reduced to 1 when it is
+ considered below. But in this case (for mv) we don't need to
+ incur the expense of recording the dev/ino => name mapping; all we
+ really need is a lookup, to see if the dev/ino pair has already
+ been copied.
- when using -H and processing a command line argument;
that command line argument could be a symlink pointing to another
command line argument. With `cp -H --preserve=link', we hard-link
@@ -1114,12 +1123,16 @@ copy_internal (const char *src_path, const char *dst_path,
command line args. Using the same hash table to preserve hard
links means that it may not be cleared. */
- if ((x->preserve_links
- && (1 < src_sb.st_nlink
- || (command_line_arg
- && x->dereference == DEREF_COMMAND_LINE_ARGUMENTS)
- || x->dereference == DEREF_ALWAYS))
- || (x->recursive && S_ISDIR (src_type)))
+ if (x->move_mode && src_sb.st_nlink == 1)
+ {
+ earlier_file = src_to_dest_lookup (src_sb.st_ino, src_sb.st_dev);
+ }
+ else if ((x->preserve_links
+ && (1 < src_sb.st_nlink
+ || (command_line_arg
+ && x->dereference == DEREF_COMMAND_LINE_ARGUMENTS)
+ || x->dereference == DEREF_ALWAYS))
+ || (x->recursive && S_ISDIR (src_type)))
{
earlier_file = remember_copied (dst_path, src_sb.st_ino, src_sb.st_dev);
}