diff --git a/src/ln/ln.rs b/src/ln/ln.rs index ad1a89b11..339efba05 100644 --- a/src/ln/ln.rs +++ b/src/ln/ln.rs @@ -189,7 +189,16 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &PathBuf, settings: &Setting let mut all_successful = true; for srcpath in files.iter() { let targetpath = match srcpath.as_os_str().to_str() { - Some(name) => target_dir.join(name), + Some(name) => { + match Path::new(name).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 bahavior of GNU + // coreutils. + None => target_dir.join(name), + } + } None => { show_error!("cannot stat '{}': No such file or directory", srcpath.display()); diff --git a/tests/test_ln.rs b/tests/test_ln.rs index 138e3b292..fad8ad4ce 100644 --- a/tests/test_ln.rs +++ b/tests/test_ln.rs @@ -1,6 +1,5 @@ use common::util::*; - #[test] fn test_symlink_existing_file() { let (at, mut ucmd) = at_and_ucmd!(); @@ -248,6 +247,32 @@ fn test_symlink_target_dir() { assert_eq!(at.resolve_link(file_b_link), file_b); } +#[test] +fn test_symlink_target_dir_from_dir() { + let (at, mut ucmd) = at_and_ucmd!(); + let dir = "test_ln_target_dir_dir"; + let from_dir = "test_ln_target_dir_from_dir"; + let filename_a = "test_ln_target_dir_file_a"; + let filename_b = "test_ln_target_dir_file_b"; + let file_a = &format!("{}/{}", from_dir, filename_a); + let file_b = &format!("{}/{}", from_dir, filename_b); + + at.mkdir(from_dir); + at.touch(file_a); + at.touch(file_b); + at.mkdir(dir); + + ucmd.args(&["-s", "-t", dir, file_a, file_b]).succeeds().no_stderr(); + + let file_a_link = &format!("{}/{}", dir, filename_a); + assert!(at.is_symlink(file_a_link)); + assert_eq!(&at.resolve_link(file_a_link), file_a); + + let file_b_link = &format!("{}/{}", dir, filename_b); + assert!(at.is_symlink(file_b_link)); + assert_eq!(&at.resolve_link(file_b_link), file_b); +} + #[test] fn test_symlink_overwrite_dir() { let (at, mut ucmd) = at_and_ucmd!();