mktemp: options support non-ut8 too

This commit is contained in:
Sylvestre Ledru
2025-08-14 10:54:17 +02:00
parent 71b4de24e6
commit 66a1fc8bbf
2 changed files with 68 additions and 20 deletions
+19 -20
View File
@@ -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,
+49
View File
@@ -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();
}