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