Skip to content

Commit b5561e7

Browse files
authored
Merge pull request #9342 from FidelSch/ln-dir-hardlink
ln: add error handling for hard link creation on directories
2 parents 4ee588e + e1f2ba1 commit b5561e7

File tree

5 files changed

+25
-3
lines changed

5 files changed

+25
-3
lines changed

src/uu/ln/locales/en-US.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@ ln-prompt-replace = replace {$file}?
3535
ln-cannot-backup = cannot backup {$file}
3636
ln-failed-to-access = failed to access {$file}
3737
ln-failed-to-create-hard-link = failed to create hard link {$source} => {$dest}
38+
ln-failed-to-create-hard-link-dir = {$source}: hard link not allowed for directory
3839
ln-backup = backup: {$backup}

src/uu/ln/locales/fr-FR.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ ln-prompt-replace = remplacer {$file} ?
3636
ln-cannot-backup = impossible de sauvegarder {$file}
3737
ln-failed-to-access = échec d'accès à {$file}
3838
ln-failed-to-create-hard-link = échec de création du lien physique {$source} => {$dest}
39+
ln-failed-to-create-hard-link-dir = {$source} : lien physique non autorisé pour un répertoire
3940
ln-backup = sauvegarde : {$backup}

src/uu/ln/src/ln.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ enum LnError {
6262

6363
#[error("{}", translate!("ln-error-extra-operand", "operand" => _0.to_string_lossy(), "program" => _1.clone()))]
6464
ExtraOperand(OsString, String),
65+
66+
#[error("{}", translate!("ln-failed-to-create-hard-link-dir", "source" => _0.to_string_lossy()))]
67+
FailedToCreateHardLinkDir(PathBuf),
6568
}
6669

6770
impl UError for LnError {
@@ -431,6 +434,12 @@ fn link(src: &Path, dst: &Path, settings: &Settings) -> UResult<()> {
431434
if settings.symbolic {
432435
symlink(&source, dst)?;
433436
} else {
437+
// Cannot create hard link to a directory directly
438+
// We can however create hard link to a symlink that points to a directory, so long as -L is not passed
439+
if src.is_dir() && (!src.is_symlink() || settings.logical) {
440+
return Err(LnError::FailedToCreateHardLinkDir(source.to_path_buf()).into());
441+
}
442+
434443
let p = if settings.logical && source.is_symlink() {
435444
// if we want to have an hard link,
436445
// source is a symlink and -L is passed

tests/by-util/test_ln.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,3 +934,17 @@ fn test_ln_non_utf8_paths() {
934934
let symlink_path = at.plus(symlink_name);
935935
assert!(symlink_path.is_symlink());
936936
}
937+
938+
#[test]
939+
fn test_ln_hard_link_dir() {
940+
let scene = TestScenario::new(util_name!());
941+
let at = &scene.fixtures;
942+
943+
at.mkdir("dir");
944+
945+
scene
946+
.ucmd()
947+
.args(&["dir", "dir_link"])
948+
.fails()
949+
.stderr_contains("hard link not allowed for directory");
950+
}

util/build-gnu.sh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,6 @@ sed -i -e "s/cat opts/sed -i -e \"s| <.\*$||g\" opts/" tests/misc/usage_vs_getop
260260
# for some reasons, some stuff are duplicated, strip that
261261
sed -i -e "s/provoked error./provoked error\ncat pat |sort -u > pat/" tests/misc/usage_vs_getopt.sh
262262

263-
# Update the GNU error message to match ours
264-
sed -i -e "s/link-to-dir: hard link not allowed for directory/failed to create hard link 'link-to-dir' =>/" -e "s|link-to-dir/: hard link not allowed for directory|failed to create hard link 'link-to-dir/' =>|" tests/ln/hard-to-sym.sh
265-
266263
# install verbose messages shows ginstall as command
267264
sed -i -e "s/ginstall: creating directory/install: creating directory/g" tests/install/basic-1.sh
268265

0 commit comments

Comments
 (0)