bug#79446: 9.7: cp(1): Unnecessary writes / incorrect logging messages

Paul Eggert <[email protected]>
Newsgroups gmane.comp.gnu.core-utils.bugs
Organization UCLA Computer Science Department
Message-ID <[email protected]>
On 2025-09-17 10:51, Kye Hunter wrote:
> I also see that (at least on my machine) changing the xattrs 
> does not affect the file's modification or change times

Well *that's* weird. I would not expect the system calls to do that. 
This whole xattr business is a bit of an undocumented zoo, I'm afraid.

> shouldn't the 
> absence of any xattrs be enough to know that they are identical?

Yes, if both files lack xattrs, their xattrs must be identical. But how 
would this idea be turned into code? Won't it require extra syscalls in 
common cases? We'd rather avoid that.

> If I add --no-preserve=mode to the command, this does prevent the extra 
> call to chmod, but adding --no-preserve=xattr still results in a call to 
> chmod, which seems odd based on your explanation.

I've lost context. How do you reproduce the bug? I just now tried "cp -p 
--no-preserve=mode --no-preserve=xattr abc def" on two files in /tmp on 
Ubuntu 25.04, and saw no call to chmod, just to fsetxattr with 
"system.posix_acl_access". The "abc" file was permission 0664 and my 
umask was 002.

> the apparent overlap in the attributes "mode" and "xattr" seems 
> sort of confusing.

No kidding. It's a mess.

> another good solution 
> here seems like it could be to remove the overlap in these two, so that 
> it would be possible to specify copying the mode/ACLs without the 
> xattrs,

Can one even do that at the syscall level? POSIX ACLs are xattrs, no?



> The first odd 
> thing would seem to be that these files are being relinked every time 
> that cp is run, even when they're already linked.

I would expect this in the normal case. What's the scenario and why 
don't you expect it in your case?


> But it gets stranger— 
> starting with an empty target directory, if I run this command:
> cp --no-preserve=links --update=older --target-directory="/home/kye/ 
> test" ./*
> then the first time I run it, the files hardlinked in the source 
> directory are not hardlinked in the target (seemingly correct), but when 
> running it the second time (and afterwards) the two files then do become 
> hardlinked, apparently contradicting the --no-preserve=links option.
> 
> So, it makes sense that hardlinked files were being hardlinked in the 
> target directory when I had --preserve=all, but maybe it doesn't make 
> sense to relinking them over-and-over when they are already linked. And 
> it seems like --update=older is somehow forcing the files to be 
> hardlinked, but only when they already exist in the target directory.

Yes, it's all fairly mysterious. Perhaps someone with more time can look 
into it.

r convenience in cases like this one?
> 
>> I have to admit I'm a bit puzzled by
>> unlinkat(3, "./CuYCWUCU", 0)            = 0
>> which would appear to be successfully removing a filename that no 
>> longer exists.
> 
> I agree, seems a bit fishy.

It's not fishy. POSIX says that rename ("CuYCWUCU", "dest") must do 
nothing and return 0 if "CuYCWUCU" and "dest" are both hard links to the 
same file. This is a bug in POSIX, and Linux unfortunately conforms to 
POSIX here. The workaround for the bug is to unlink ("CuYCWUCU") after 
renaming it to "dest"; the unlink succeeds if and only if the bug was 
triggered.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.