Skip to content

cp: error on -s with relative source and destination outside cwd - #15300

Open
henrimarconni wants to merge 9 commits into
uutils:mainfrom
henrimarconni:main
Open

henrimarconni wants to merge 9 commits into
uutils:mainfrom
henrimarconni:main

Conversation

@henrimarconni

Copy link
Copy Markdown

Removes one of the inconsistencies listed in #15254

cp -s b.txt sub created sub/b.txt -> b.txt, a dangling self-referential symlink, and exited 0. GNU refuses with:

cp: sub/b.txt: can make relative symbolic links only in current directory

and exits 1. A relative symlink target is resolved from the link's own directory, so it can't point back to ./b.txt from inside sub/.

Changes

  • In handle_copy_mode (CopyMode::SymLink), return an error when the source is not absolute and the destination's parent is not the current directory.
  • Add the cp-error-relative-symlink-not-in-cwd message to en-US.ftl and fr-FR.ftl.
  • Add tests for the failing case and for the cases that must still succeed (relative source with destination in cwd, absolute source into a subdirectory).

Behavior

Before:

exit: 0; files: sub/b.txt l mode 777

After:

exit: 1; cp: sub/b.txt: can make relative symbolic links only in current directory
image

Comment thread src/uu/cp/locales/fr-FR.ftl Outdated
Comment thread src/uu/cp/src/cp.rs Outdated
Comment thread src/uu/cp/src/cp.rs Outdated
Comment thread tests/by-util/test_cp.rs Outdated
@henrimarconni

Copy link
Copy Markdown
Author

Thanks for the review :)
I have modified the code as you said:

  1. Moved the check to the start of copy_file function to prevent file destruction bugs when using --remove-destination flag
  2. Added more test cases
  3. Fixed WASI CI/CD failure (tests that pass an absolute host path are ignored on the WASI runner, since the sandbox cannot see the host tmpdir)

Comment thread src/uu/cp/src/cp.rs Outdated
Comment thread src/uu/cp/src/cp.rs Outdated
Comment thread tests/by-util/test_cp.rs
Now, the verify_relative_symlink_in_cwd function compares dir_name(dest)
with "." by name first and then by
device and inode. If the parent is not trivially ".", stat both "." and
the parent and compare their FileInformation. If either stat fails, the
destination is treated as outside the cwd.
@henrimarconni

Copy link
Copy Markdown
Author

Thanks for the review, all addressed:

  • Added cp -rs dir out with a relative dir (refused) and the
    absolute-source counterpart (still works).
  • ../<cwd>/b2: good catch, that was a bug. GNU compares
    dir_name(dest) with "." by name and then by device/inode, so it
    accepts this. Fixed to match, with tests for it and for a symlink
    to the cwd.
  • Merged the "./" test into test_cp_symlink_relative_source_in_cwd,
    which now loops over "b2.txt" and "./b2.txt".

@codspeed

codspeed Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Merging this PR will improve performance by 3.56%

⚠️ 118 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

ℹ️ 1 benchmark has no flame graph

The flamegraph could not be generated because too much time was spent in runtime internals, making the visualization not useful for performance analysis.

⚡ 1 improved benchmark
✅ 400 untouched benchmarks
⏩ 70 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
⚡ ⚠️ Simulation sort_reverse_utf8_locale 82 ms 79.2 ms +3.56%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing henrimarconni:main (350371a) with main (80fd308)2

Open in CodSpeed

Footnotes

  1. 70 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. ↩

  2. No successful run was found on main (9c28184) during the generation of this report, so 80fd308 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

Comment thread tests/by-util/test_cp.rs Outdated
Co-authored-by: Eduardo M. Rodrigues <16357187+eduardomourar@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants