Skip to content

Commit d6af68a

Browse files
authored
Merge pull request #6922 from uutils/revert-6595-install_copy_permission
Revert "install: create destination file with safer modes before copy"
2 parents d878f6c + 0780e26 commit d6af68a

File tree

2 files changed

+14
-80
lines changed

2 files changed

+14
-80
lines changed

src/uu/install/src/install.rs

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,9 @@ use filetime::{set_file_times, FileTime};
1313
use std::error::Error;
1414
use std::fmt::{Debug, Display};
1515
use std::fs;
16-
#[cfg(not(unix))]
1716
use std::fs::File;
1817
use std::os::unix::fs::MetadataExt;
1918
#[cfg(unix)]
20-
use std::os::unix::fs::OpenOptionsExt;
21-
#[cfg(unix)]
2219
use std::os::unix::prelude::OsStrExt;
2320
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
2421
use std::process;
@@ -753,52 +750,27 @@ fn perform_backup(to: &Path, b: &Behavior) -> UResult<Option<PathBuf>> {
753750
fn copy_file(from: &Path, to: &Path) -> UResult<()> {
754751
// fs::copy fails if destination is a invalid symlink.
755752
// so lets just remove all existing files at destination before copy.
756-
let remove_destination = || {
757-
if let Err(e) = fs::remove_file(to) {
758-
if e.kind() != std::io::ErrorKind::NotFound {
759-
show_error!(
760-
"Failed to remove existing file {}. Error: {:?}",
761-
to.display(),
762-
e
763-
);
764-
}
753+
if let Err(e) = fs::remove_file(to) {
754+
if e.kind() != std::io::ErrorKind::NotFound {
755+
show_error!(
756+
"Failed to remove existing file {}. Error: {:?}",
757+
to.display(),
758+
e
759+
);
765760
}
766-
};
767-
remove_destination();
768-
769-
// create the destination file first. Using safer mode on unix to avoid
770-
// potential unsafe mode between time-of-creation and time-of-chmod.
771-
#[cfg(unix)]
772-
let creation = fs::OpenOptions::new()
773-
.write(true)
774-
.create_new(true)
775-
.mode(0o600)
776-
.open(to);
777-
#[cfg(not(unix))]
778-
let creation = File::create(to);
779-
780-
if let Err(e) = creation {
781-
show_error!(
782-
"Failed to create destination file {}. Error: {:?}",
783-
to.display(),
784-
e
785-
);
786-
return Err(InstallError::InstallFailed(from.to_path_buf(), to.to_path_buf(), e).into());
787761
}
788762

789-
// drop the file to close the fd of creation
790-
drop(creation);
791-
792-
/* workaround a limitation of fs::copy: skip copy if source is /dev/null
793-
* https://github.com/rust-lang/rust/issues/79390
794-
*/
795-
if from.as_os_str() != "/dev/null" {
796-
if let Err(err) = fs::copy(from, to) {
797-
remove_destination();
763+
if from.as_os_str() == "/dev/null" {
764+
/* workaround a limitation of fs::copy
765+
* https://github.com/rust-lang/rust/issues/79390
766+
*/
767+
if let Err(err) = File::create(to) {
798768
return Err(
799769
InstallError::InstallFailed(from.to_path_buf(), to.to_path_buf(), err).into(),
800770
);
801771
}
772+
} else if let Err(err) = fs::copy(from, to) {
773+
return Err(InstallError::InstallFailed(from.to_path_buf(), to.to_path_buf(), err).into());
802774
}
803775
Ok(())
804776
}

tests/by-util/test_install.rs

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,41 +1717,3 @@ fn test_install_root_combined() {
17171717
run_and_check(&["-Cv", "c", "d"], "d", 0, 0);
17181718
run_and_check(&["-Cv", "c", "d"], "d", 0, 0);
17191719
}
1720-
1721-
#[cfg(all(unix, feature = "chmod"))]
1722-
#[test]
1723-
fn test_install_copy_failures() {
1724-
let scene = TestScenario::new(util_name!());
1725-
1726-
let at = &scene.fixtures;
1727-
1728-
let file1 = "source_file";
1729-
let file2 = "target_file";
1730-
1731-
at.touch(file1);
1732-
scene.ccmd("chmod").arg("000").arg(file1).succeeds();
1733-
1734-
// if source file is not readable, it will raise a permission error.
1735-
// since we create the file with mode 0600 before `fs::copy`, if the
1736-
// copy failed, the file should be removed.
1737-
scene
1738-
.ucmd()
1739-
.arg(file1)
1740-
.arg(file2)
1741-
.arg("--mode=400")
1742-
.fails()
1743-
.stderr_contains("permission denied");
1744-
assert!(!at.file_exists(file2));
1745-
1746-
// if source file is good to copy, it should succeed and set the
1747-
// destination file permissions accordingly
1748-
scene.ccmd("chmod").arg("644").arg(file1).succeeds();
1749-
scene
1750-
.ucmd()
1751-
.arg(file1)
1752-
.arg(file2)
1753-
.arg("--mode=400")
1754-
.succeeds();
1755-
assert!(at.file_exists(file2));
1756-
assert_eq!(0o100_400_u32, at.metadata(file2).permissions().mode());
1757-
}

0 commit comments

Comments
 (0)