bug-coreutils
[Top][All Lists]
Advanced

[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

Attachment: smime.p7s
Description: S/MIME cryptographic signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]