mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
touch: fix handling of non-UTF-8 filenames
This commit is contained in:
+17
-11
@@ -157,7 +157,7 @@ fn is_first_filename_timestamp(
|
||||
reference: Option<&OsString>,
|
||||
date: Option<&str>,
|
||||
timestamp: Option<&str>,
|
||||
files: &[&String],
|
||||
files: &[&OsString],
|
||||
) -> bool {
|
||||
if timestamp.is_none()
|
||||
&& reference.is_none()
|
||||
@@ -166,8 +166,11 @@ fn is_first_filename_timestamp(
|
||||
// env check is last as the slowest op
|
||||
&& matches!(std::env::var("_POSIX2_VERSION").as_deref(), Ok("199209"))
|
||||
{
|
||||
let s = files[0];
|
||||
all_digits(s) && (s.len() == 8 || (s.len() == 10 && (69..=99).contains(&get_year(s))))
|
||||
if let Some(s) = files[0].to_str() {
|
||||
all_digits(s) && (s.len() == 8 || (s.len() == 10 && (69..=99).contains(&get_year(s))))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -189,8 +192,8 @@ fn shr2(s: &str) -> String {
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let matches = uu_app().get_matches_from_localized(args);
|
||||
|
||||
let mut filenames: Vec<&String> = matches
|
||||
.get_many::<String>(ARG_FILES)
|
||||
let mut filenames: Vec<&OsString> = matches
|
||||
.get_many::<OsString>(ARG_FILES)
|
||||
.ok_or_else(|| {
|
||||
USimpleError::new(
|
||||
1,
|
||||
@@ -211,12 +214,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
.map(|t| t.to_owned());
|
||||
|
||||
if is_first_filename_timestamp(reference, date.as_deref(), timestamp.as_deref(), &filenames) {
|
||||
timestamp = if filenames[0].len() == 10 {
|
||||
Some(shr2(filenames[0]))
|
||||
} else {
|
||||
Some(filenames[0].to_string())
|
||||
};
|
||||
filenames = filenames[1..].to_vec();
|
||||
if let Some(first_file) = filenames[0].to_str() {
|
||||
timestamp = if first_file.len() == 10 {
|
||||
Some(shr2(first_file))
|
||||
} else {
|
||||
Some(first_file.to_string())
|
||||
};
|
||||
filenames = filenames[1..].to_vec();
|
||||
}
|
||||
}
|
||||
|
||||
let source = if let Some(reference) = reference {
|
||||
@@ -338,6 +343,7 @@ pub fn uu_app() -> Command {
|
||||
Arg::new(ARG_FILES)
|
||||
.action(ArgAction::Append)
|
||||
.num_args(1..)
|
||||
.value_parser(clap::value_parser!(OsString))
|
||||
.value_hint(clap::ValueHint::AnyPath),
|
||||
)
|
||||
.group(
|
||||
|
||||
@@ -1013,3 +1013,26 @@ fn test_touch_f_option() {
|
||||
assert!(at.file_exists(file));
|
||||
at.remove(file);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_touch_non_utf8_paths() {
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
// Create a test file with non-UTF-8 bytes in the name
|
||||
let non_utf8_bytes = b"test_\xFF\xFE.txt";
|
||||
let non_utf8_name = OsStr::from_bytes(non_utf8_bytes);
|
||||
|
||||
// Test that touch handles non-UTF-8 file names without crashing
|
||||
let result = scene.ucmd().arg(non_utf8_name).succeeds();
|
||||
|
||||
// Verify no output and file was created
|
||||
result.no_output();
|
||||
|
||||
// Check that the file was created (using the raw path)
|
||||
assert!(std::fs::metadata(at.plus(non_utf8_name)).is_ok());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user