Igor Giamoniano <[email protected]> writes:

> When using mv --exchange and the destination path does not exist, mv
> fails before issuing the renameat2 system call and prints
> "Unknown error -1" instead of the expected "No such file or directory".
> The exit status (1) is correct; only the error message is wrong.
>
>
> *Reproduction:*
>   $ touch a
>   $ LC_ALL=C mv --exchange a b
>   mv: cannot exchange 'a' and 'b': Unknown error -1
>
> *Expected:*
>
>   mv: cannot exchange 'a' and 'b': No such file or directory
>
> Strace shows that the stat of the destination returns ENOENT, and no
> renameat2 call is made:
>
>   openat(AT_FDCWD, "b", O_RDONLY|O_PATH|O_DIRECTORY) = -1 ENOENT (No such
> file or directory)
>   newfstatat(AT_FDCWD, "a", {st_mode=S_IFREG|0600, st_size=0, ...},
> AT_SYMLINK_NOFOLLOW) = 0
>   newfstatat(AT_FDCWD, "b", 0x7fffdf0654e0, AT_SYMLINK_NOFOLLOW) = -1
> ENOENT (No such file or directory)
>   mv: cannot exchange 'a' and 'b': Unknown error -1
>
> So the -1 is not returned by the kernel. Refusing the exchange is fine
> since the destination doesn't exist; only the message is wrong. My
> guess, from the strace only, is that the ENOENT is not passed to the
> error message.
>
> The same happens when the destination is an existing directory and -T
> is not used: mv tries dest/source, that path does not exist, and the
> same "Unknown error -1" appears.
>
> When both files exist but are on different file systems, renameat2 is
> called, returns EXDEV, and the message is correct ("Invalid cross-device
> link").
>
> *Reproduced on:*
>
>   coreutils 9.7 (Debian 13, container)
>   coreutils 9.11 (NixOS, kernel 6.18.56, glibc 2.42)
>
> I checked the git log on master and found no related commit after 9.11.

Thanks for the detailed report!

I can reproduce it on coreutils-9.12 as well. I'll take a look at it
later today.

Collin



Reply via email to