From 66a1fc8bbf1278de9a12be181a216dec55a00f4d Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 12 Aug 2025 00:40:02 +0200 Subject: [PATCH] mktemp: options support non-ut8 too --- src/uu/mktemp/src/mktemp.rs | 39 ++++++++++++++-------------- tests/by-util/test_mktemp.rs | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/uu/mktemp/src/mktemp.rs b/src/uu/mktemp/src/mktemp.rs index 98ffdadbf..ceb8605bf 100644 --- a/src/uu/mktemp/src/mktemp.rs +++ b/src/uu/mktemp/src/mktemp.rs @@ -235,10 +235,7 @@ impl Params { let tmpdir = options.tmpdir; let prefix_from_option = tmpdir.clone().unwrap_or_default(); let prefix_from_template = &template_str[..i]; - let prefix = Path::new(&prefix_from_option) - .join(prefix_from_template) - .display() - .to_string(); + let prefix_path = Path::new(&prefix_from_option).join(prefix_from_template); if options.treat_as_template && prefix_from_template.contains(MAIN_SEPARATOR) { return Err(MkTempError::PrefixContainsDirSeparator( template_str.to_string(), @@ -250,21 +247,23 @@ impl Params { // Split the parent directory from the file part of the prefix. // - // For example, if `prefix` is "a/b/c/d", then `directory` is - // "a/b/c" is `prefix` gets reassigned to "d". - let (directory, prefix) = if prefix.ends_with(MAIN_SEPARATOR) { - (prefix, String::new()) - } else { - let path = Path::new(&prefix); - let directory = match path.parent() { - None => String::new(), - Some(d) => d.display().to_string(), - }; - let prefix = match path.file_name() { - None => String::new(), - Some(f) => f.to_str().unwrap().to_string(), - }; - (directory, prefix) + // For example, if `prefix_path` is "a/b/c/d", then `directory` is + // "a/b/c" and `prefix` gets reassigned to "d". + let (directory, prefix) = { + let prefix_str = prefix_path.to_string_lossy(); + if prefix_str.ends_with(MAIN_SEPARATOR) { + (prefix_path, String::new()) + } else { + let directory = match prefix_path.parent() { + None => PathBuf::new(), + Some(d) => d.to_path_buf(), + }; + let prefix = match prefix_path.file_name() { + None => String::new(), + Some(f) => f.to_str().unwrap().to_string(), + }; + (directory, prefix) + } }; // Combine the suffix from the template with the suffix given as an option. @@ -285,7 +284,7 @@ impl Params { let num_rand_chars = j - i; Ok(Self { - directory: directory.into(), + directory, prefix, num_rand_chars, suffix, diff --git a/tests/by-util/test_mktemp.rs b/tests/by-util/test_mktemp.rs index 872924eb3..405c7bfee 100644 --- a/tests/by-util/test_mktemp.rs +++ b/tests/by-util/test_mktemp.rs @@ -1011,3 +1011,52 @@ fn test_non_utf8_template() { ts.ucmd().arg(template).fails().stderr_contains("invalid"); } + +#[test] +#[cfg(target_os = "linux")] +fn test_non_utf8_tmpdir_path() { + use std::os::unix::ffi::OsStrExt; + let (at, mut ucmd) = at_and_ucmd!(); + + // Create a directory with non-UTF8 bytes + let dir_name = std::ffi::OsStr::from_bytes(b"test_dir_\xFF\xFE"); + std::fs::create_dir(at.plus(dir_name)).unwrap(); + + // Test that mktemp can handle non-UTF8 directory paths with -p option + ucmd.arg("-p").arg(at.plus(dir_name)).succeeds(); +} + +#[test] +#[cfg(target_os = "linux")] +fn test_non_utf8_tmpdir_long_option() { + use std::os::unix::ffi::OsStrExt; + let (at, mut ucmd) = at_and_ucmd!(); + + // Create a directory with non-UTF8 bytes + let dir_name = std::ffi::OsStr::from_bytes(b"test_dir_\xFF\xFE"); + std::fs::create_dir(at.plus(dir_name)).unwrap(); + + // Test that mktemp can handle non-UTF8 directory paths with --tmpdir option + // Note: Due to test framework limitations with non-UTF8 arguments and --tmpdir= syntax, + // we'll test a more limited scenario that still validates non-UTF8 path handling + ucmd.arg("-p") + .arg(at.plus(dir_name)) + .arg("tmpXXXXXX") + .succeeds(); +} + +#[test] +#[cfg(target_os = "linux")] +fn test_non_utf8_tmpdir_directory_creation() { + use std::os::unix::ffi::OsStrExt; + let (at, mut ucmd) = at_and_ucmd!(); + + // Create a directory with non-UTF8 bytes + let dir_name = std::ffi::OsStr::from_bytes(b"test_dir_\xFF\xFE"); + std::fs::create_dir(at.plus(dir_name)).unwrap(); + + // Test directory creation (-d flag) with non-UTF8 directory paths + // We can't easily verify the exact output path because of UTF8 conversion issues, + // but we can verify the command succeeds + ucmd.arg("-d").arg("-p").arg(at.plus(dir_name)).succeeds(); +}