diff --git a/src/uu/realpath/src/realpath.rs b/src/uu/realpath/src/realpath.rs index 1b4ea6028..f855f5cea 100644 --- a/src/uu/realpath/src/realpath.rs +++ b/src/uu/realpath/src/realpath.rs @@ -5,8 +5,9 @@ // spell-checker:ignore (ToDO) retcode -use clap::{Arg, ArgAction, ArgMatches, Command, builder::NonEmptyStringValueParser}; +use clap::{Arg, ArgAction, ArgMatches, Command}; use std::{ + ffi::OsString, io::{Write, stdout}, path::{Path, PathBuf}, }; @@ -40,7 +41,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { /* the list of files */ let paths: Vec = matches - .get_many::(ARG_FILES) + .get_many::(ARG_FILES) .unwrap() .map(PathBuf::from) .collect(); @@ -145,21 +146,21 @@ pub fn uu_app() -> Command { Arg::new(OPT_RELATIVE_TO) .long(OPT_RELATIVE_TO) .value_name("DIR") - .value_parser(NonEmptyStringValueParser::new()) + .value_parser(clap::value_parser!(OsString)) .help(translate!("realpath-help-relative-to")), ) .arg( Arg::new(OPT_RELATIVE_BASE) .long(OPT_RELATIVE_BASE) .value_name("DIR") - .value_parser(NonEmptyStringValueParser::new()) + .value_parser(clap::value_parser!(OsString)) .help(translate!("realpath-help-relative-base")), ) .arg( Arg::new(ARG_FILES) .action(ArgAction::Append) .required(true) - .value_parser(NonEmptyStringValueParser::new()) + .value_parser(clap::value_parser!(OsString)) .value_hint(clap::ValueHint::AnyPath), ) } @@ -174,10 +175,10 @@ fn prepare_relative_options( resolve_mode: ResolveMode, ) -> UResult<(Option, Option)> { let relative_to = matches - .get_one::(OPT_RELATIVE_TO) + .get_one::(OPT_RELATIVE_TO) .map(PathBuf::from); let relative_base = matches - .get_one::(OPT_RELATIVE_BASE) + .get_one::(OPT_RELATIVE_BASE) .map(PathBuf::from); let relative_to = canonicalize_relative_option(relative_to, can_mode, resolve_mode)?; let relative_base = canonicalize_relative_option(relative_base, can_mode, resolve_mode)?; diff --git a/tests/by-util/test_realpath.rs b/tests/by-util/test_realpath.rs index ee156f5d0..bc1bf9276 100644 --- a/tests/by-util/test_realpath.rs +++ b/tests/by-util/test_realpath.rs @@ -464,3 +464,28 @@ fn test_realpath_trailing_slash() { fn test_realpath_empty() { new_ucmd!().fails_with_code(1); } + +#[test] +#[cfg(target_os = "linux")] +fn test_realpath_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); + + // Create the actual file + at.touch(non_utf8_name); + + // Test that realpath handles non-UTF-8 paths without crashing + let result = scene.ucmd().arg(non_utf8_name).succeeds(); + + // The result should contain the non-UTF-8 bytes + let output = result.stdout_str_lossy(); + assert!(output.contains("test_")); + assert!(output.contains(".txt")); +}