diff --git a/src/uu/mktemp/src/mktemp.rs b/src/uu/mktemp/src/mktemp.rs index 8f99ecca7bd..ce648c3e10b 100644 --- a/src/uu/mktemp/src/mktemp.rs +++ b/src/uu/mktemp/src/mktemp.rs @@ -16,6 +16,7 @@ use uucore::format_usage; use std::env; use std::error::Error; use std::fmt::Display; +use std::io::ErrorKind; use std::iter; use std::path::{Path, PathBuf, MAIN_SEPARATOR}; @@ -54,6 +55,9 @@ enum MkTempError { SuffixContainsDirSeparator(String), InvalidTemplate(String), TooManyTemplates, + + /// When a specified temporary directory could not be found. + NotFound(String, String), } impl UError for MkTempError { @@ -93,6 +97,12 @@ impl Display for MkTempError { TooManyTemplates => { write!(f, "too many templates") } + NotFound(template_type, s) => write!( + f, + "failed to create {} via template {}: No such file or directory", + template_type, + s.quote() + ), } } } @@ -461,7 +471,8 @@ pub fn dry_exec(tmpdir: &str, prefix: &str, rand: usize, suffix: &str) -> UResul /// /// # Errors /// -/// If the temporary directory could not be written to disk. +/// If the temporary directory could not be written to disk or if the +/// given directory `dir` does not exist. fn make_temp_dir(dir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult { let mut builder = Builder::new(); builder.prefix(prefix).rand_bytes(rand).suffix(suffix); @@ -473,6 +484,12 @@ fn make_temp_dir(dir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult< fs::set_permissions(&path, fs::Permissions::from_mode(0o700))?; Ok(path) } + Err(e) if e.kind() == ErrorKind::NotFound => { + let filename = format!("{}{}{}", prefix, "X".repeat(rand), suffix); + let path = Path::new(dir).join(filename); + let s = path.display().to_string(); + Err(MkTempError::NotFound("directory".to_string(), s).into()) + } Err(e) => Err(e.into()), } } @@ -486,7 +503,8 @@ fn make_temp_dir(dir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult< /// /// # Errors /// -/// If the file could not be written to disk. +/// If the file could not be written to disk or if the directory does +/// not exist. fn make_temp_file(dir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult { let mut builder = Builder::new(); builder.prefix(prefix).rand_bytes(rand).suffix(suffix); @@ -496,6 +514,12 @@ fn make_temp_file(dir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult Ok((_, pathbuf)) => Ok(pathbuf), Err(e) => Err(MkTempError::PersistError(e.file.path().to_path_buf()).into()), }, + Err(e) if e.kind() == ErrorKind::NotFound => { + let filename = format!("{}{}{}", prefix, "X".repeat(rand), suffix); + let path = Path::new(dir).join(filename); + let s = path.display().to_string(); + Err(MkTempError::NotFound("file".to_string(), s).into()) + } Err(e) => Err(e.into()), } } diff --git a/tests/by-util/test_mktemp.rs b/tests/by-util/test_mktemp.rs index 8b58672a2d6..2f7d748b5fe 100644 --- a/tests/by-util/test_mktemp.rs +++ b/tests/by-util/test_mktemp.rs @@ -735,3 +735,27 @@ fn test_tmpdir_env_var() { assert_matches_template!(template, filename); assert!(at.file_exists(filename)); } + +#[test] +fn test_nonexistent_tmpdir_env_var() { + new_ucmd!() + .env(TMPDIR, "no/such/dir") + .fails() + .stderr_only("mktemp: failed to create file via template 'no/such/dir/tmp.XXXXXXXXXX': No such file or directory\n"); + + new_ucmd!() + .arg("-d") + .env(TMPDIR, "no/such/dir") + .fails() + .stderr_only("mktemp: failed to create directory via template 'no/such/dir/tmp.XXXXXXXXXX': No such file or directory\n"); +} + +#[test] +fn test_nonexistent_dir_prefix() { + new_ucmd!().arg("d/XXX").fails().stderr_only( + "mktemp: failed to create file via template 'd/XXX': No such file or directory\n", + ); + new_ucmd!().args(&["-d", "d/XXX"]).fails().stderr_only( + "mktemp: failed to create directory via template 'd/XXX': No such file or directory\n", + ); +}