diff --git a/src/uu/ln/locales/en-US.ftl b/src/uu/ln/locales/en-US.ftl index 337d5c2a0d9..5afa83d4314 100644 --- a/src/uu/ln/locales/en-US.ftl +++ b/src/uu/ln/locales/en-US.ftl @@ -29,7 +29,6 @@ ln-error-missing-destination = missing destination file operand after {$operand} ln-error-extra-operand = extra operand {$operand} Try '{$program} --help' for more information. ln-error-could-not-update = Could not update {$target}: {$error} -ln-error-cannot-stat = cannot stat {$path}: No such file or directory ln-error-will-not-overwrite = will not overwrite just-created {$target} with {$source} ln-prompt-replace = replace {$file}? ln-cannot-backup = cannot backup {$file} diff --git a/src/uu/ln/locales/fr-FR.ftl b/src/uu/ln/locales/fr-FR.ftl index d8ba0996722..2be821c2734 100644 --- a/src/uu/ln/locales/fr-FR.ftl +++ b/src/uu/ln/locales/fr-FR.ftl @@ -30,7 +30,6 @@ ln-error-missing-destination = opérande de fichier de destination manquant apr ln-error-extra-operand = opérande supplémentaire {$operand} Essayez « {$program} --help » pour plus d'informations. ln-error-could-not-update = Impossible de mettre à jour {$target} : {$error} -ln-error-cannot-stat = impossible d'analyser {$path} : Aucun fichier ou répertoire de ce nom ln-error-will-not-overwrite = ne remplacera pas le fichier {$target} qui vient d'être créé par {$source} ln-prompt-replace = remplacer {$file} ? ln-cannot-backup = impossible de sauvegarder {$file} diff --git a/src/uu/ln/src/ln.rs b/src/uu/ln/src/ln.rs index 1c7d40b8476..5812d51a683 100644 --- a/src/uu/ln/src/ln.rs +++ b/src/uu/ln/src/ln.rs @@ -334,22 +334,15 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &Path, settings: &Settings) } } target_dir.to_path_buf() - } else if let Some(name) = srcpath.as_os_str().to_str() { - match Path::new(name).file_name() { + } else { + match srcpath.file_name() { Some(basename) => target_dir.join(basename), // This can be None only for "." or "..". Trying // to create a link with such name will fail with // EEXIST, which agrees with the behavior of GNU // coreutils. - None => target_dir.join(name), + None => target_dir.join(srcpath), } - } else { - show_error!( - "{}", - translate!("ln-error-cannot-stat", "path" => srcpath.quote()) - ); - all_successful = false; - continue; }; if linked_destinations.contains(&targetpath) { diff --git a/tests/by-util/test_ln.rs b/tests/by-util/test_ln.rs index 560a7364f2f..bc06956e8c6 100644 --- a/tests/by-util/test_ln.rs +++ b/tests/by-util/test_ln.rs @@ -378,6 +378,51 @@ fn test_symlink_target_dir() { assert_eq!(at.resolve_link(file_b_link), file_b); } +#[test] +#[cfg(target_os = "linux")] +fn test_symlink_target_dir_non_utf8_source_name() { + use std::ffi::OsStr; + use std::fs; + use std::os::unix::ffi::OsStrExt; + + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + let target_dir = "test_symlink_target_dir_non_utf8"; + let source_bytes = b"source_\xFF\xFE"; + let source_name = OsStr::from_bytes(source_bytes); + + at.mkdir(target_dir); + at.touch(source_name); + + scene + .ucmd() + .args(&["-s", "-t", target_dir]) + .arg(source_name) + .succeeds() + .no_stderr(); + + let target_dir_path = at.plus(target_dir); + let mut dir_entries = fs::read_dir(&target_dir_path) + .expect("reading target directory entries after creating symlink"); + let created_entry = dir_entries + .next() + .expect("finding created entry in target directory") + .expect("reading created target-directory entry"); + assert!( + dir_entries.next().is_none(), + "expected only one created entry in target directory" + ); + assert_eq!( + created_entry.file_name().as_os_str().as_bytes(), + source_bytes + ); + + let created_link_path = target_dir_path.join(source_name); + let created_link_target = fs::read_link(&created_link_path) + .expect("reading created symlink target in target directory"); + assert_eq!(created_link_target.as_os_str().as_bytes(), source_bytes); +} + #[test] fn test_symlink_target_dir_from_dir() { let (at, mut ucmd) = at_and_ucmd!();