[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#43958: `cp --archive --symbolic-link` non-reproducible and creates h
From: |
Martin Ramsdale (mramsdal) |
Subject: |
bug#43958: `cp --archive --symbolic-link` non-reproducible and creates hardlinks between symbolic links that dereference to the same inode |
Date: |
Mon, 12 Oct 2020 10:45:26 +0000 |
Dear coreutils maintainers,
I've encountered, what I consider, a bug in GNU cp: If you do a recursive
copy, then any files with identical inodes from the source will be created
with new-identical inodes in the destination. For example:
$ mkdir copy_from
$ echo aaa > copy_from/file1
$ ln copy_from/file1 copy_from/file2
$ cp -as "$(pwd)"/copy_from/ copy_to
$ stat -c '%n %i' copy_to/file*
copy_to/file1 42615790
copy_to/file2 42615790
$ ls -l copy_to/file*
copy_to/file1 -> /gnu_cp_bug/copy_from/file1
copy_to/file2 -> /gnu_cp_bug/copy_from/file1
Whereas the expected result is:
$ ls -l copy_to/file*
copy_to/file1 -> /gnu_cp_bug/copy_from/file1
copy_to/file2 -> /gnu_cp_bug/copy_from/file2
Issues this can cause include:
1) Incorrect file usage:
Whilst initially any usage of copy_to/file[1,2] is as expected, if any
of copy_from/file[1,2] is *replaced* (rather than modified), then usage of
copy_to/file[1,2] will yield unexpected results. For example:
$ rm copy_from/file2
$ echo bbb > copy_from/file2
$ cat copy_from/file*
aaa
bbb
$ cat copy_to/file*
aaa
aaa
2) Non-reproducible behaviour: symlinks created may point to any of the
original inodes, and so for the same input directory the output of `copy
-as` may differ. For example invocations on different systems could yield
either:
> ls -l copy_to/file*
copy_to/file1 -> /gnu_cp_bug/copy_from/file1
copy_to/file2 -> /gnu_cp_bug/copy_from/file1
OR
> ls -l copy_to/file*
copy_to/file1 -> /gnu_cp_bug/copy_from/file2
copy_to/file2 -> /gnu_cp_bug/copy_from/file2
>From brief code inspection, I believe this issue to orginiate from
earlier_file lookup in copy_internal(). I haven't had the opportunity to
build/validate this as a fix, but propose the following for consideration:
diff --git a/src/copy.c b/src/copy.c
index 4050f6953..74c1e7499 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -2513,6 +2513,8 @@ copy_internal (char const *src_name, char const
*dst_name,
{
if (command_line_arg)
earlier_file = remember_copied (dst_name, src_sb.st_ino,
src_sb.st_dev);
+ else if (x->symbolic_link)
+ earlier_file = NULL;
else
earlier_file = src_to_dest_lookup (src_sb.st_ino, src_sb.st_dev);
}
Kind Regards,
Martin
smime.p7s
Description: S/MIME cryptographic signature
- bug#43958: `cp --archive --symbolic-link` non-reproducible and creates hardlinks between symbolic links that dereference to the same inode,
Martin Ramsdale (mramsdal) <=