mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
ln: fix handling of non-UTF-8 filenames
This commit is contained in:
+8
-6
@@ -34,7 +34,7 @@ pub struct Settings {
|
||||
symbolic: bool,
|
||||
relative: bool,
|
||||
logical: bool,
|
||||
target_dir: Option<String>,
|
||||
target_dir: Option<PathBuf>,
|
||||
no_target_dir: bool,
|
||||
no_dereference: bool,
|
||||
verbose: bool,
|
||||
@@ -102,7 +102,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
/* the list of files */
|
||||
|
||||
let paths: Vec<PathBuf> = matches
|
||||
.get_many::<String>(ARG_FILES)
|
||||
.get_many::<OsString>(ARG_FILES)
|
||||
.unwrap()
|
||||
.map(PathBuf::from)
|
||||
.collect();
|
||||
@@ -131,8 +131,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
logical,
|
||||
relative: matches.get_flag(options::RELATIVE),
|
||||
target_dir: matches
|
||||
.get_one::<String>(options::TARGET_DIRECTORY)
|
||||
.map(String::from),
|
||||
.get_one::<OsString>(options::TARGET_DIRECTORY)
|
||||
.map(PathBuf::from),
|
||||
no_target_dir: matches.get_flag(options::NO_TARGET_DIRECTORY),
|
||||
no_dereference: matches.get_flag(options::NO_DEREFERENCE),
|
||||
verbose: matches.get_flag(options::VERBOSE),
|
||||
@@ -210,6 +210,7 @@ pub fn uu_app() -> Command {
|
||||
.help(translate!("ln-help-target-directory"))
|
||||
.value_name("DIRECTORY")
|
||||
.value_hint(clap::ValueHint::DirPath)
|
||||
.value_parser(clap::value_parser!(OsString))
|
||||
.conflicts_with(options::NO_TARGET_DIRECTORY),
|
||||
)
|
||||
.arg(
|
||||
@@ -238,6 +239,7 @@ pub fn uu_app() -> Command {
|
||||
Arg::new(ARG_FILES)
|
||||
.action(ArgAction::Append)
|
||||
.value_hint(clap::ValueHint::AnyPath)
|
||||
.value_parser(clap::value_parser!(OsString))
|
||||
.required(true)
|
||||
.num_args(1..),
|
||||
)
|
||||
@@ -245,9 +247,9 @@ pub fn uu_app() -> Command {
|
||||
|
||||
fn exec(files: &[PathBuf], settings: &Settings) -> UResult<()> {
|
||||
// Handle cases where we create links in a directory first.
|
||||
if let Some(ref name) = settings.target_dir {
|
||||
if let Some(ref target_path) = settings.target_dir {
|
||||
// 4th form: a directory is specified by -t.
|
||||
return link_files_in_dir(files, &PathBuf::from(name), settings);
|
||||
return link_files_in_dir(files, target_path, settings);
|
||||
}
|
||||
if !settings.no_target_dir {
|
||||
if files.len() == 1 {
|
||||
|
||||
@@ -843,3 +843,46 @@ fn test_ln_seen_file() {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_ln_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);
|
||||
let non_utf8_link_bytes = b"link_\xFF\xFE.txt";
|
||||
let non_utf8_link_name = OsStr::from_bytes(non_utf8_link_bytes);
|
||||
|
||||
// Create the actual file
|
||||
at.touch(non_utf8_name);
|
||||
|
||||
// Test creating a hard link with non-UTF-8 file names
|
||||
scene.ucmd()
|
||||
.arg(non_utf8_name)
|
||||
.arg(non_utf8_link_name)
|
||||
.succeeds();
|
||||
|
||||
// Both files should exist
|
||||
assert!(at.file_exists(non_utf8_name));
|
||||
assert!(at.file_exists(non_utf8_link_name));
|
||||
|
||||
// Test creating a symbolic link with non-UTF-8 file names
|
||||
let symlink_bytes = b"symlink_\xFF\xFE.txt";
|
||||
let symlink_name = OsStr::from_bytes(symlink_bytes);
|
||||
|
||||
scene.ucmd()
|
||||
.args(&["-s"])
|
||||
.arg(non_utf8_name)
|
||||
.arg(symlink_name)
|
||||
.succeeds();
|
||||
|
||||
// Check if symlink was created successfully
|
||||
let symlink_path = at.plus(symlink_name);
|
||||
assert!(symlink_path.is_symlink());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user