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
