Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/uu/ln/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ ln-prompt-replace = replace {$file}?
ln-cannot-backup = cannot backup {$file}
ln-failed-to-access = failed to access {$file}
ln-failed-to-create-hard-link = failed to create hard link {$source} => {$dest}
ln-failed-to-create-hard-link-dir = {$source}: hard link not allowed for directory
ln-backup = backup: {$backup}
1 change: 1 addition & 0 deletions src/uu/ln/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ ln-prompt-replace = remplacer {$file} ?
ln-cannot-backup = impossible de sauvegarder {$file}
ln-failed-to-access = échec d'accès à {$file}
ln-failed-to-create-hard-link = échec de création du lien physique {$source} => {$dest}
ln-failed-to-create-hard-link-dir = {$source} : lien physique non autorisé pour un répertoire
ln-backup = sauvegarde : {$backup}
8 changes: 8 additions & 0 deletions src/uu/ln/src/ln.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ enum LnError {

#[error("{}", translate!("ln-error-extra-operand", "operand" => _0.to_string_lossy(), "program" => _1.clone()))]
ExtraOperand(OsString, String),

#[error("{}", translate!("ln-failed-to-create-hard-link-dir", "source" => _0.to_string_lossy()))]
FailedToCreateHardLinkDir(PathBuf),
}

impl UError for LnError {
Expand Down Expand Up @@ -431,6 +434,11 @@ fn link(src: &Path, dst: &Path, settings: &Settings) -> UResult<()> {
if settings.symbolic {
symlink(&source, dst)?;
} else {
// Cannot create hard link to a directory
if src.is_dir() {
return Err(LnError::FailedToCreateHardLinkDir(source.to_path_buf()).into());
}

let p = if settings.logical && source.is_symlink() {
// if we want to have an hard link,
// source is a symlink and -L is passed
Expand Down
16 changes: 16 additions & 0 deletions tests/by-util/test_ln.rs
Original file line number Diff line number Diff line change
Expand Up @@ -934,3 +934,19 @@ fn test_ln_non_utf8_paths() {
let symlink_path = at.plus(symlink_name);
assert!(symlink_path.is_symlink());
}

#[test]
fn test_ln_hard_link_dir() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;

at.mkdir("dir");

let result = scene.ucmd().args(&["dir", "dir_link"]).fails();

assert!(
result
.stderr_str()
.contains("hard link not allowed for directory")
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A detail: you can simplify the code a bit by using stderr_contains:

Suggested change
let result = scene.ucmd().args(&["dir", "dir_link"]).fails();
assert!(
result
.stderr_str()
.contains("hard link not allowed for directory")
);
scene
.ucmd()
.args(&["dir", "dir_link"])
.fails()
.stderr_contains("hard link not allowed for directory");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

totally missed that, adding it now

}
Loading