Repository navigation
chown, chgrp: keep -h separate from -H/-L traversal - #15127
abendrothj wants to merge 5 commits into
Conversation
84a606f to
4a5f167
Compare
Merging this PR will degrade performance by 19.29%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Simulation | three_39_bit_primes |
583.2 ms | 860.7 ms | -32.24% |
| ❌ |
Simulation | du_wide_tree[(5000, 500)] |
15.5 ms | 16.1 ms | -3.86% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing abendrothj:chown-h-with-dereference (98a54f0) with main (6292c03)
Footnotes
-
54 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
4a5f167 to
5409d04
Compare
--from was checked on a stat of the name and the change was then made by name, so a rename landing in between changed a file that never had the required owner. On Linux, hold the file open with O_PATH, check that it is the one that was stat'd and still passes --from, and change it through that descriptor with fchownat(AT_EMPTY_PATH). This covers operands and -R entries. A file found replaced is left alone; as with GNU, that fails without a message, and -v reports the change that was not made.
On Linux, a directory operand was changed through a descriptor opened for reading, and when that open failed it was skipped without a message. Change it by name then, or through an O_PATH descriptor with --from, as for any other file. Under -R it is still left alone and the failure to read it reported, as with GNU.
Under -R -H, a symlink met in the tree was stat'd itself, while the change went to the file it points to. --from was judged on, and -v reported, the link's owner. Use the target's, as GNU does.
With -R on Linux, a change below the operand that failed was reported without the "failed to change" line that -v adds for the operand and on other platforms.
With -h, `-R -H` and `-R -L` did not descend into a symlinked directory operand, and `-R -L -h` changed the files that symlinks in the tree point to rather than the links. As GNU does, follow such a symlink to descend and to judge --from, and change the link itself.
5409d04 to
98a54f0
Compare
With -h, -H and -L were also used to decide whether to change links, so
-RHh/-RLhdidn't descend through the operand link, and-RLhchanged link targets instead of the links.Traversal now follows -H/-L, and whether a link or its target is changed follows -h. When a link is changed, an owner or group that wasn't given stays unchanged instead of being copied from the target. On Linux, over 36 commands the exit status and final ownership match GNU 9.12; the -v text still differs as on main (unrequested IDs printed, operand before descendants). Tests:
test_chown_h_follows_symlink_operand_under_big_h_and_l,test_chown_big_l_with_h_changes_symlinks_in_tree.Based on #15126.
Closes #15116