mirror of
https://github.com/uutils/coreutils
synced 2024-10-01 13:35:03 +00:00
gnu cp-parents
test case (#6446)
This commit is contained in:
parent
ef68e60c85
commit
e46ad30434
|
@ -431,7 +431,9 @@ pub(crate) fn copy_directory(
|
|||
let dest = target.join(root.file_name().unwrap());
|
||||
copy_attributes(root, dest.as_path(), &options.attributes)?;
|
||||
for (x, y) in aligned_ancestors(root, dest.as_path()) {
|
||||
copy_attributes(x, y, &options.attributes)?;
|
||||
if let Ok(src) = canonicalize(x, MissingHandling::Normal, ResolveMode::Physical) {
|
||||
copy_attributes(&src, y, &options.attributes)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
copy_attributes(root, target, &options.attributes)?;
|
||||
|
|
|
@ -1332,7 +1332,11 @@ fn construct_dest_path(
|
|||
Ok(match target_type {
|
||||
TargetType::Directory => {
|
||||
let root = if options.parents {
|
||||
if source_path.has_root() && cfg!(unix) {
|
||||
Path::new("/")
|
||||
} else {
|
||||
Path::new("")
|
||||
}
|
||||
} else {
|
||||
source_path.parent().unwrap_or(source_path)
|
||||
};
|
||||
|
@ -1380,7 +1384,9 @@ fn copy_source(
|
|||
);
|
||||
if options.parents {
|
||||
for (x, y) in aligned_ancestors(source, dest.as_path()) {
|
||||
copy_attributes(x, y, &options.attributes)?;
|
||||
if let Ok(src) = canonicalize(x, MissingHandling::Normal, ResolveMode::Physical) {
|
||||
copy_attributes(&src, y, &options.attributes)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
res
|
||||
|
@ -1443,8 +1449,8 @@ pub(crate) fn copy_attributes(
|
|||
|
||||
let dest_uid = source_metadata.uid();
|
||||
let dest_gid = source_metadata.gid();
|
||||
|
||||
wrap_chown(
|
||||
// gnu compatibility: cp doesn't report an error if it fails to set the ownership.
|
||||
let _ = wrap_chown(
|
||||
dest,
|
||||
&dest.symlink_metadata().context(context)?,
|
||||
Some(dest_uid),
|
||||
|
@ -1452,11 +1458,9 @@ pub(crate) fn copy_attributes(
|
|||
false,
|
||||
Verbosity {
|
||||
groups_only: false,
|
||||
level: VerbosityLevel::Normal,
|
||||
level: VerbosityLevel::Silent,
|
||||
},
|
||||
)
|
||||
.map_err(Error::Error)?;
|
||||
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
|
@ -2163,7 +2167,13 @@ fn copy_file(
|
|||
fs::set_permissions(dest, dest_permissions).ok();
|
||||
}
|
||||
|
||||
if options.dereference(source_in_command_line) {
|
||||
if let Ok(src) = canonicalize(source, MissingHandling::Normal, ResolveMode::Physical) {
|
||||
copy_attributes(&src, dest, &options.attributes)?;
|
||||
}
|
||||
} else {
|
||||
copy_attributes(source, dest, &options.attributes)?;
|
||||
}
|
||||
|
||||
copied_files.insert(
|
||||
FileInformation::from_path(source, options.dereference(source_in_command_line))?,
|
||||
|
|
|
@ -5573,3 +5573,89 @@ fn test_preserve_attrs_overriding_2() {
|
|||
assert_ne!(dest_file1_metadata.ino(), dest_file2_metadata.ino());
|
||||
}
|
||||
}
|
||||
|
||||
/// Test the behavior of preserving permissions when copying through a symlink
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_cp_symlink_permissions() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch("a");
|
||||
at.set_mode("a", 0o700);
|
||||
at.symlink_file("a", "symlink");
|
||||
at.mkdir("dest");
|
||||
scene
|
||||
.ucmd()
|
||||
.args(&["--preserve", "symlink", "dest"])
|
||||
.succeeds();
|
||||
let dest_dir_metadata = at.metadata("dest/symlink");
|
||||
let src_dir_metadata = at.metadata("a");
|
||||
assert_eq!(
|
||||
src_dir_metadata.permissions().mode(),
|
||||
dest_dir_metadata.permissions().mode()
|
||||
);
|
||||
}
|
||||
|
||||
/// Test the behavior of preserving permissions of parents when copying through a symlink
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_cp_parents_symlink_permissions_file() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.mkdir("a");
|
||||
at.touch("a/file");
|
||||
at.set_mode("a", 0o700);
|
||||
at.symlink_dir("a", "symlink");
|
||||
at.mkdir("dest");
|
||||
scene
|
||||
.ucmd()
|
||||
.args(&["--parents", "-a", "symlink/file", "dest"])
|
||||
.succeeds();
|
||||
let dest_dir_metadata = at.metadata("dest/symlink");
|
||||
let src_dir_metadata = at.metadata("a");
|
||||
assert_eq!(
|
||||
src_dir_metadata.permissions().mode(),
|
||||
dest_dir_metadata.permissions().mode()
|
||||
);
|
||||
}
|
||||
|
||||
/// Test the behavior of preserving permissions of parents when copying through
|
||||
/// a symlink when source is a dir.
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_cp_parents_symlink_permissions_dir() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.mkdir_all("a/b");
|
||||
at.set_mode("a", 0o755); // Set mode for the actual directory
|
||||
at.symlink_dir("a", "symlink");
|
||||
at.mkdir("dest");
|
||||
scene
|
||||
.ucmd()
|
||||
.args(&["--parents", "-a", "symlink/b", "dest"])
|
||||
.succeeds();
|
||||
let dest_dir_metadata = at.metadata("dest/symlink");
|
||||
let src_dir_metadata = at.metadata("a");
|
||||
assert_eq!(
|
||||
src_dir_metadata.permissions().mode(),
|
||||
dest_dir_metadata.permissions().mode()
|
||||
);
|
||||
}
|
||||
|
||||
/// Test the behavior of copying a file to a destination with parents using absolute paths.
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn test_cp_parents_absolute_path() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.mkdir_all("a/b");
|
||||
at.touch("a/b/f");
|
||||
at.mkdir("dest");
|
||||
let src = format!("{}/a/b/f", at.root_dir_resolved());
|
||||
scene
|
||||
.ucmd()
|
||||
.args(&["--parents", src.as_str(), "dest"])
|
||||
.succeeds();
|
||||
let res = format!("dest{}/a/b/f", at.root_dir_resolved());
|
||||
at.file_exists(res);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue