Subject: bug#36818: closed (Re: bug#36818: mv fails to clobber target if it's a hardlink of a source)

From: [email-masked] (GNU bug Tracking System)
Date: Fri, 26 Jul 2019 18:24:03 +0000

Your bug report

#36818: mv fails to clobber target if it's a hardlink of a source

which was filed against the coreutils package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
36818: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=36818
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#36818: mv fails to clobber target if it's a hardlink of a source
From: Sergei Trofimovich <[email-masked]>
To: Eric Blake <[email-masked]>, [email-masked]
Cc: [email-masked]
Date: Fri, 26 Jul 2019 19:23:22 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

On Fri, 26 Jul 2019 13:01:44 -0500
Eric Blake <[email-masked]> wrote:

> On 7/26/19 12:43 PM, Sergei Trofimovich wrote:
> 
> > Is it an 'mv's bug or a feature to prevent hardlinked file clobbering?
> > If feels like an unnecessary restriction.  
> 
> It's a POSIX (mis-)feature that for hard links, rename("file1", "file2")
> is a mandatory no-op (no error, but also no change to the existence or
> contents of either file1 or file2).  Back under POSIX 2001, mv was
> required to behave identically to the rename() syscall.  But this was
> confusing enough that POSIX 2008 relaxed the wording as follows,
> inspired in part by complaint from GNU coreutils:
> 
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html
> 
> "If the source_file operand and destination path resolve to either the
> same existing directory entry or different directory entries for the
> same existing file, then the destination path shall not be removed, and
> one of the following shall occur:
> 
>     No change is made to source_file, no error occurs, and no diagnostic
> is issued.
> 
>     No change is made to source_file, a diagnostic is issued to standard
> error identifying the two names, and the exit status is affected.
> 
>     If the source_file operand and destination path name distinct
> directory entries, then the source_file operand is removed, no error
> occurs, and no diagnostic is issued."
> 
> The difference between GNU coreutils and busybox both appear to be
> compliant behaviors (you didn't actually show after the 'mv' command
> whether a.aa still exists, so I can't tell whether busybox implemented
> option 1 or option 3;

Oh, I did not realize source file did not disappear.

Looks like busybox's behaviour is an 'option 1':

  $ ls -i a.aa b.bb
  208636260 a.aa  208636260 b.bb

  $ strace -f busybox mv a.aa b.bb
  ...
  stat("b.bb", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
  access("b.bb", W_OK)                    = 0
  rename("a.aa", "b.bb")                  = 0
  exit_group(0)                           = ?
  +++ exited with 0 +++

  $ ls -i a.aa b.bb
  208636260 a.aa  208636260 b.bb

> but it appears GNU implemented option 2).  Option
> 1 is probably the least intuitive but is the historical behavior when
> you use rename() without any checking.  Option 2 at least points out the
> issue that your usage is not going to be universally portable.  Option 3
> is closest to what happens when there are no hard links.

Thank you for the quick response. The bug can be closed as WAI then.

-- 

  Sergei

Subject: mv fails to clobber target if it's a hardlink of a source
From: Sergei Trofimovich <[email-masked]>
To: [email-masked]
Date: Fri, 26 Jul 2019 18:43:51 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

The below is a bug initially reported by Xuefer at https://bugs.gentoo.org/646412.

Reproducer:

  $ mv --version
  mv (GNU coreutils) 8.31
  Packaged by Gentoo (8.31 (p0))

  $ touch a.aa
  $ ln a.aa b.bb
  $ mv a.aa b.bb
  mv: 'a.aa' and 'b.bb' are the same file

For comparison if fines are unrelated 'mv' just works:

  $ touch a.aa
  $ touch b.bb
  $ mv a.aa b.bb
  $ echo $?
  0

Fun fact: busybox does not complain about hardlinked files:

  $ touch a.aa
  $ ln a.aa b.bb
  $ busybox mv a.aa b.bb
  $ echo $?
  $ echo $?
  0

Some context on where these accidentally hardlinked files come from:

gdb build system simplistically does the following:
    $ gcc a.c -o a.tmp.o && mv a.tmp.o a.o

ccache has a mode to create a resulting file by hardlinking
if possible instead of copying data round.

If the above command is ran without ccache wrapper 'a.tmp.o'
is always a new file. Otherwise if it's ran via ccache with
CCACHE_HARDLINK=1 then 'a.tmp.o' and 'a.o' and both
hardlinks of a file stored in cache originally.

Is it an 'mv's bug or a feature to prevent hardlinked file clobbering?
If feels like an unnecessary restriction.

Thank you!

-- 

  Sergei