From ee4691f4a2f9b5942d87646d204fcec6da9f4cd1 Mon Sep 17 00:00:00 2001 From: Guillaume Ranquet Date: Thu, 1 Jun 2023 17:16:46 +0200 Subject: [PATCH] cp: makes --preserve requires = prevents --preserve to eat the next argument when no value is passed. default value for --preserve is set to mode,ownership(unix only),timestamps before the patch: cp --preserve foo bar error: invalid value 'foo' for '--preserve [...]' [possible values: mode, ownership, timestamps, context, link, links, xattr, all] Signed-off-by: Guillaume Ranquet --- src/uu/cp/src/cp.rs | 1 + tests/by-util/test_cp.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index e8552a179fb..60ef540954a 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -515,6 +515,7 @@ pub fn uu_app() -> Command { PRESERVABLE_ATTRIBUTES, )) .num_args(0..) + .require_equals(true) .value_name("ATTR_LIST") .overrides_with_all([ options::ARCHIVE, diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 9ccf6777ed8..fa5845eac35 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -1223,6 +1223,33 @@ fn test_cp_preserve_no_args() { } } +#[test] +fn test_cp_preserve_no_args_before_opts() { + let (at, mut ucmd) = at_and_ucmd!(); + let src_file = "a"; + let dst_file = "b"; + + // Prepare the source file + at.touch(src_file); + #[cfg(unix)] + at.set_mode(src_file, 0o0500); + + // Copy + ucmd.arg("--preserve") + .arg(src_file) + .arg(dst_file) + .succeeds(); + + #[cfg(all(unix, not(target_os = "freebsd")))] + { + // Assert that the mode, ownership, and timestamps are preserved + // NOTICE: the ownership is not modified on the src file, because that requires root permissions + let metadata_src = at.metadata(src_file); + let metadata_dst = at.metadata(dst_file); + assert_metadata_eq!(metadata_src, metadata_dst); + } +} + #[test] fn test_cp_preserve_all() { let (at, mut ucmd) = at_and_ucmd!();