From 51383e10e65aa77c83c5789267977824e0ef9aee Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Thu, 11 Feb 2021 15:59:58 +0100 Subject: [PATCH] Fix: install /dev/null target (#1646) * fix(install): workaround the /dev/null bug Caused by a limitation of fs::copy in rust. see: https://github.com/rust-lang/rust/issues/79390 --- src/uu/install/src/install.rs | 24 ++++++++++++++++++------ tests/by-util/test_install.rs | 8 -------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/uu/install/src/install.rs b/src/uu/install/src/install.rs index 3f3502cb6..b41b16ef6 100644 --- a/src/uu/install/src/install.rs +++ b/src/uu/install/src/install.rs @@ -17,6 +17,7 @@ use uucore::entries::{grp2gid, usr2uid}; use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity}; use std::fs; +use std::fs::File; use std::os::unix::fs::MetadataExt; use std::path::{Path, PathBuf}; use std::result::Result; @@ -419,7 +420,7 @@ fn standard(paths: Vec, b: Behavior) -> i32 { /// fn copy_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behavior) -> i32 { if !target_dir.is_dir() { - show_error!("target ‘{}’ is not a directory", target_dir.display()); + show_error!("target '{}' is not a directory", target_dir.display()); return 1; } @@ -429,7 +430,7 @@ fn copy_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behavior) -> Some(name) => target_dir.join(name), None => { show_error!( - "cannot stat ‘{}’: No such file or directory", + "cannot stat '{}': No such file or directory", sourcepath.display() ); @@ -479,11 +480,22 @@ fn copy_file_to_file(file: &PathBuf, target: &PathBuf, b: &Behavior) -> i32 { /// If the copy system call fails, we print a verbose error and return an empty error value. /// fn copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> Result<(), ()> { - let io_result = fs::copy(from, to); - - if let Err(err) = io_result { + if from.to_string_lossy() == "/dev/null" { + /* workaround a limitation of fs::copy + * https://github.com/rust-lang/rust/issues/79390 + */ + if let Err(err) = File::create(to) { + show_error!( + "install: cannot install '{}' to '{}': {}", + from.display(), + to.display(), + err + ); + return Err(()); + } + } else if let Err(err) = fs::copy(from, to) { show_error!( - "cannot install ‘{}’ to ‘{}’: {}", + "cannot install '{}' to '{}': {}", from.display(), to.display(), err diff --git a/tests/by-util/test_install.rs b/tests/by-util/test_install.rs index 99e2abfd4..a04c0ddfc 100644 --- a/tests/by-util/test_install.rs +++ b/tests/by-util/test_install.rs @@ -330,14 +330,6 @@ fn test_install_target_file_dev_null() { let file1 = "/dev/null"; let file2 = "test_install_target_file_file_i2"; - at.touch(file1); - at.touch(file2); - ucmd.arg(file1).arg(file2).fails(); - - /* Uncomment when fixed ucmd.arg(file1).arg(file2).succeeds().no_stderr(); - - assert!(at.file_exists(file1)); assert!(at.file_exists(file2)); - */ }