From 1ffad8228aa33190415f4ee8bf77639ef711f037 Mon Sep 17 00:00:00 2001 From: Chris Dryden Date: Wed, 10 Dec 2025 03:22:04 -0500 Subject: [PATCH] cp: Enabling cp force flag to run on windows (#9624) * Enabling cp force flag to run on windows * Windows requires clearing the readonly permissions before deleting --- src/uu/cp/src/cp.rs | 12 ++++++++++-- tests/by-util/test_cp.rs | 2 -- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index 9ef767d05..650ec1348 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -987,8 +987,6 @@ impl Options { let not_implemented_opts = vec![ #[cfg(not(any(windows, unix)))] options::ONE_FILE_SYSTEM, - #[cfg(windows)] - options::FORCE, ]; for not_implemented_opt in not_implemented_opts { @@ -1991,6 +1989,16 @@ fn delete_dest_if_needed_and_allowed( } fn delete_path(path: &Path, options: &Options) -> CopyResult<()> { + // Windows requires clearing readonly attribute before deletion when using --force + #[cfg(windows)] + if options.force() { + if let Ok(mut perms) = fs::metadata(path).map(|m| m.permissions()) { + #[allow(clippy::permissions_set_readonly_false)] + perms.set_readonly(false); + let _ = fs::set_permissions(path, perms); + } + } + match fs::remove_file(path) { Ok(()) => { if options.verbose { diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 7562eab38..e8f6765cb 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -11,7 +11,6 @@ use uucore::selinux::get_getfattr_output; use uutests::util::TestScenario; use uutests::{at_and_ucmd, new_ucmd, path_concat, util_name}; -#[cfg(not(windows))] use std::fs::set_permissions; use std::io::Write; @@ -972,7 +971,6 @@ fn test_cp_arg_no_clobber_twice() { } #[test] -#[cfg(not(windows))] fn test_cp_arg_force() { let (at, mut ucmd) = at_and_ucmd!();