1
0
mirror of https://github.com/uutils/coreutils synced 2024-07-01 06:54:36 +00:00

gnu cp-parents test case (#6446)

This commit is contained in:
sreehari prasad 2024-06-17 14:46:26 +05:30 committed by GitHub
parent ef68e60c85
commit e46ad30434
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 108 additions and 10 deletions

View File

@ -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)?;

View File

@ -1332,7 +1332,11 @@ fn construct_dest_path(
Ok(match target_type {
TargetType::Directory => {
let root = if options.parents {
Path::new("")
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();
}
copy_attributes(source, dest, &options.attributes)?;
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))?,

View File

@ -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);
}