Fix stdbuf to handle non-UTF-8 filenames

This commit is contained in:
Sylvestre Ledru
2025-08-14 10:52:24 +02:00
parent f02436be0f
commit b5f8931b17
4 changed files with 38 additions and 13 deletions
+1 -2
View File
@@ -6,8 +6,7 @@
// spell-checker:ignore (ToDO) COMFOLLOW Chowner RFILE RFILE's derefer dgid nonblank nonprint nonprinting
use uucore::display::Quotable;
pub use uucore::entries;
use uucore::display::Quotable;
use uucore::entries;
use uucore::error::{FromIo, UResult, USimpleError};
use uucore::format_usage;
use uucore::perms::{GidUidOwnerFilter, IfFrom, chown_base, options};
+13 -8
View File
@@ -201,12 +201,11 @@ fn find_last_contiguous_block_of_xs(s: &str) -> Option<(usize, usize)> {
impl Params {
fn from(options: Options) -> Result<Self, MkTempError> {
// Convert OsString template to string for processing
let template_str = match options.template.to_str() {
Some(s) => s,
None => {
// For non-UTF-8 templates, return an error
return Err(MkTempError::InvalidTemplate(options.template.to_string_lossy().into_owned()));
}
let Some(template_str) = options.template.to_str() else {
// For non-UTF-8 templates, return an error
return Err(MkTempError::InvalidTemplate(
options.template.to_string_lossy().into_owned(),
));
};
// The template argument must end in 'X' if a suffix option is given.
@@ -241,7 +240,9 @@ impl Params {
.display()
.to_string();
if options.treat_as_template && prefix_from_template.contains(MAIN_SEPARATOR) {
return Err(MkTempError::PrefixContainsDirSeparator(template_str.to_string()));
return Err(MkTempError::PrefixContainsDirSeparator(
template_str.to_string(),
));
}
if tmpdir.is_some() && Path::new(prefix_from_template).is_absolute() {
return Err(MkTempError::InvalidTemplate(template_str.to_string()));
@@ -465,7 +466,11 @@ pub fn uu_app() -> Command {
.help(translate!("mktemp-help-t"))
.action(ArgAction::SetTrue),
)
.arg(Arg::new(ARG_TEMPLATE).num_args(..=1).value_parser(clap::value_parser!(OsString)))
.arg(
Arg::new(ARG_TEMPLATE)
.num_args(..=1)
.value_parser(clap::value_parser!(OsString)),
)
}
fn dry_exec(tmpdir: &Path, prefix: &str, rand: usize, suffix: &str) -> UResult<PathBuf> {
+5 -3
View File
@@ -6,6 +6,7 @@
// spell-checker:ignore (ToDO) tempdir dyld dylib optgrps libstdbuf
use clap::{Arg, ArgAction, ArgMatches, Command};
use std::ffi::OsString;
use std::os::unix::process::ExitStatusExt;
use std::path::PathBuf;
use std::process;
@@ -183,9 +184,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let options =
ProgramOptions::try_from(&matches).map_err(|e| UUsageError::new(125, e.to_string()))?;
let mut command_values = matches.get_many::<String>(options::COMMAND).unwrap();
let mut command_values = matches.get_many::<OsString>(options::COMMAND).unwrap();
let mut command = process::Command::new(command_values.next().unwrap());
let command_params: Vec<&str> = command_values.map(|s| s.as_ref()).collect();
let command_params: Vec<&OsString> = command_values.collect();
let tmp_dir = tempdir().unwrap();
let (preload_env, libstdbuf) = get_preload_env(&tmp_dir)?;
@@ -269,6 +270,7 @@ pub fn uu_app() -> Command {
.action(ArgAction::Append)
.hide(true)
.required(true)
.value_hint(clap::ValueHint::CommandName),
.value_hint(clap::ValueHint::CommandName)
.value_parser(clap::value_parser!(OsString)),
)
}
+19
View File
@@ -3,6 +3,8 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore dyld dylib setvbuf
#[cfg(target_os = "linux")]
use uutests::at_and_ucmd;
use uutests::new_ucmd;
#[cfg(not(target_os = "windows"))]
use uutests::util::TestScenario;
@@ -216,3 +218,20 @@ fn test_libstdbuf_preload() {
"uutils echo should not show architecture mismatch"
);
}
#[cfg(target_os = "linux")]
#[test]
fn test_stdbuf_non_utf8_paths() {
use std::os::unix::ffi::OsStringExt;
let (at, mut ucmd) = at_and_ucmd!();
let filename = std::ffi::OsString::from_vec(vec![0xFF, 0xFE]);
std::fs::write(at.plus(&filename), b"test content for stdbuf\n").unwrap();
ucmd.arg("-o0")
.arg("cat")
.arg(&filename)
.succeeds()
.stdout_is("test content for stdbuf\n");
}