Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

martinkunkel2
Copy link
Contributor

@martinkunkel2 martinkunkel2 commented Aug 19, 2025

So far cp only checked if the metadata of the destination file indicates
read-only permissions. In order to handle the case where the destination
file is in use, we try to open the destination file for writing. Also
other cases which prevent overwriting can be detected that way.

For the test case we copy the coreutils binary to a test directory. Then
use the copy to try to copy a file over itself. This should fail in
non-force mode, but succeed in force mode.

this fixes #8261

Copy link

GNU testsuite comparison:

GNU test failed: tests/cp/special-f. tests/cp/special-f is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/misc/stdbuf (passes in this run but fails in the 'main' branch)

@martinkunkel2
Copy link
Contributor Author

ok, this does not work (related GNU test fails). I'll further investigate.

@martinkunkel2 martinkunkel2 force-pushed the cp-issue-8261 branch 2 times, most recently from 14837cc to 9e89ef5 Compare August 19, 2025 16:03
@martinkunkel2 martinkunkel2 changed the title cp: force: open dest. to check for required delete cp: force mode: try to open destination for write in order to check for required delete Aug 19, 2025
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/stdbuf (passes in this run but fails in the 'main' branch)

@martinkunkel2 martinkunkel2 changed the title cp: force mode: try to open destination for write in order to check for required delete cp: force mode: try to open destination for write to check if delete is required Aug 19, 2025
is_symlink_loop(dest) || fs::metadata(dest)?.permissions().readonly()
is_symlink_loop(dest)
|| fs::metadata(dest)?.permissions().readonly()
|| (dest.is_file() && OpenOptions::new().write(true).open(dest).is_err())
Copy link
Contributor

Choose a reason for hiding this comment

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

The condition dest.is_file() check seems redundant since
OpenOptions::new().write(true).open(dest) will fail on non-files anyway, and this creates an unnecessary extra syscall

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried that first, but the open(dest) gets stuck when the destination is a FIFO. It does not return.

So far cp only checked if the metadata of the destination file indicates
read-only permissions. In order to handle the case where the destination
file is in use, we try to open the destination file for writing. Also
other cases which prevent overwriting can be detected that way.

For the test case we copy the coreutils binary to a test directory. Then
use the copy to try to copy a file over itself. This should fail in
non-force mode, but succeed in force mode.
@martinkunkel2
Copy link
Contributor Author

@sylvestre thank you for your review. I addressed the findings. Please check.

@sylvestre
Copy link
Contributor

fails here:

---- test_cp::test_cp_dest_in_use stdout ----
bin: "/home/runner.linux/work/target/debug/coreutils"

thread 'test_cp::test_cp_dest_in_use' panicked at tests/by-util/test_cp.rs:6895:10:
Failed to execute command: Os { code: 26, kind: ExecutableFileBusy, message: "Text file busy" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    test_cp::test_cp_dest_in_use

test result: FAILED. 3810 passed; 1 failed; 40 ignored; 0 measured; 0 filtered out; finished in 77.11s

Copy link

GNU testsuite comparison:

GNU test failed: tests/cp/cross-dev-symlink. tests/cp/cross-dev-symlink is passing on 'main'. Maybe you have to rebase?
Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)

@martinkunkel2
Copy link
Contributor Author

ok, this needs more investigations. I'll change the PR back to draft.

@martinkunkel2 martinkunkel2 marked this pull request as draft August 22, 2025 19:44
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: refuses to overwrite binary in use
2 participants