You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ln -f removes the destination before attempting the link, so a failed link destroys it #14550
ln -f A B unlinks B first and only then calls link. When the link fails, B is already gone and the diagnostic talks only about the source. GNU tries the link first and unlinks only on EEXIST, so the destination survives every failed link.
$ echo keep > B
$ ln -f nonexistent B ;echo"exit=$?"; cat B
source
uutils 0.11.0 / main
GNU 9.11
missing
exit 1, B deleted
exit 1, B keeps its contents
a directory
exit 1, B deleted
exit 1, B keeps its contents
dangling symlink with -L
exit 1, B deleted
exit 1, B keeps its contents
All three verified on main against GNU 9.11.
Cause
In the OverwriteMode::Force arm of link() (src/uu/ln/src/ln.rs:436) the destination is removed unconditionally, and everything that can make the link fail comes after it: the -L resolution at ln.rs:454 and fs::hard_link at ln.rs:463. The Err(_) if p.is_dir() arm that prints "hard link not allowed for directory" is diagnosing a failure that has already cost the destination.
GNU's ln.c documents the deliberate opposite order - POSIX 2008 lets an application fail early if it can prove continuing cannot succeed, so it links to a temporary name in the destination's directory and renames it over B. That also removes the window during a successfulln -f where B briefly does not exist at all.
Suggested fix
Attempt the link first and take the force path only on AlreadyExists; resolve -L and reject a directory source before removing anything. Better, link under a temporary name and rename over dst, as GNU does.
Affected: 0.11.0 and main. Reported privately by Hongkai Chen (SEFCOM Lab, Arizona State University); handled as a normal bug rather than an advisory.
Activity
ln: keep the destination when a forced link fails
ln: keep the destination when a forced link fails
ln: keep the destination when a forced link fails