diff options
author | Jim Meyering <jim@meyering.net> | 2004-03-12 11:53:18 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2004-03-12 11:53:18 +0000 |
commit | bcea8e96ea30693a05fcee2ae49aa9aea0e5e7da (patch) | |
tree | 21062827a4d04c6d45a160925c771f6d426c7827 | |
parent | 04975d25921447c96db51fc76b02bc31d8848f0a (diff) | |
download | coreutils-bcea8e96ea30693a05fcee2ae49aa9aea0e5e7da.tar.xz |
Sometimes, when source and destination partition are different,
mv mistakenly fails to preserve a hard link. Reported by IIDA Yosiaki.
When moving a set of N hard-linked files between
partitions, via two or more command line arguments where the
command line argument containing the Nth link contains no other
link to that same file, mv would mistakenly copy the file, rather
than hard-linking it to the other(s). That happens because when the
final link is processed, its link count has been reduced to 1 since
the other links have been `copied' to the destination partition
and the source links have been removed.
(copy_internal): When in move mode, use the source dev/inode
pair to look up destination name even when st_nlink == 1.
-rw-r--r-- | src/copy.c | 25 |
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); } |