Skip to content

cp: fix recursive copy of a filesystem root such as W:/ on Windows - #15700

Open
armadavalor wants to merge 2 commits into
uutils:mainfrom
armadavalor:fix-cp-windows-drive-root
Open

armadavalor wants to merge 2 commits into
uutils:mainfrom
armadavalor:fix-cp-windows-drive-root

Conversation

@armadavalor

Copy link
Copy Markdown
Contributor

Fixes #5166

cp -r W:/ dest on Windows failed with 'W:/id.dat' and 'W:/id.dat' are the same file.

A filesystem root has no parent, so Context::new leaves root_parent as None, and get_local_to_root_parent then returned the absolute source path unchanged. Entry::new does target.join(descendant), and joining an absolute path (or one with a drive prefix) discards target, so every entry was mapped onto itself. With W:/* it worked because the glob gives root_parent = Some(..).

The None arm now drops the Prefix and RootDir components, so the entries are placed relative to the target (dest/id.dat, dest/sub/x.txt). This is not Windows-specific logic: cp -r / dest goes through the same path, so I added a portable unit test as well as a Windows one.

Testing:

  • unit tests in copydir.rs (one portable, one cfg(windows))
  • manual, on Windows: subst Q: <dir> then cp -r Q:/ dest and cp -r Q:\ dest — before: the "same file" error, after: dest/id.dat, dest/sub/x.txt
  • cargo test --features cp --test tests test_cp:: gives the same result before and after the change (136 passed, 41 failed); all 41 are tests that create symlinks, which need a privilege this Windows machine lacks.

I did not add an integration test in tests/by-util/test_cp.rs, since reproducing the bug needs a drive root (subst/mounted volume), which isn't reliably available in CI. Happy to add one if you have a preferred approach.

I have not verified the Unix side (cp -r / dest) by running it.

🤖 Generated with Claude Code

Fixes uutils#5166

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Comment thread src/uu/cp/src/copydir.rs Outdated
.filter(|c| {
!matches!(
c,
std::path::Component::Prefix(_) | std::path::Component::RootDir

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please import std::path::Component? it would fit on one line

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.

cp: wrong target path on Windows

2 participants