commit: 0320e0b9c5421835fb612a6dc25fd455827997d0
parent 8990b1c0acc2bc5035351c1ff33ba2acaf59868f
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Mon, 4 Aug 2025 06:52:59 +0200
cmd/ln: only omit O_NOFOLLOW when disambiguating target argument
Diffstat:
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/cmd/ln.c b/cmd/ln.c
@@ -23,7 +23,8 @@ const char *argv0 = "ln";
static bool opt_s = false, force = false;
static int link_flags = 0;
-static int open_dest_flags = O_RDONLY | O_PATH;
+static int open_target_flags = O_RDONLY | O_PATH;
+static int open_dest_flags = O_RDONLY | O_PATH | O_NOFOLLOW;
static struct stat dest_stat;
static int
@@ -182,7 +183,7 @@ main(int argc, char *argv[])
force = true;
break;
case 'n':
- FIELD_SET(open_dest_flags, O_NOFOLLOW);
+ FIELD_SET(open_target_flags, O_NOFOLLOW);
break;
case 's':
opt_s = true;
@@ -221,7 +222,7 @@ main(int argc, char *argv[])
}
else if(argc == 2)
{
- int targetfd = open(target, open_dest_flags);
+ int targetfd = open(target, open_target_flags);
if(targetfd >= 0)
{
if(fstat(targetfd, &dest_stat) < 0)
diff --git a/test-cmd/ln.sh b/test-cmd/ln.sh
@@ -2,7 +2,7 @@
# SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
# SPDX-License-Identifier: MPL-2.0
-plans=59
+plans=63
WD=$(dirname "$0")
target="${WD}/../cmd/ln"
. "${WD}/tap.sh"
@@ -94,9 +94,16 @@ t_args 'implicit_dest' '' -sn //example.org
t_readlink ./example.org //example.org
t_cmd '' '' rm ./example.org
-t_args 'dest_broken_symlink:create' '' -s /var/empty/e/no/ent dest_broken_symlink
+t_args 'target_broken_symlink:create' '' -s /var/empty/e/no/ent target_broken_symlink
+t_args --exit=1 'target_broken_symlink' "\
+ln: error: Destination 'target_broken_symlink' already exists
+" -s //example.org target_broken_symlink
+t_args 'target_broken_symlink:force' '' -sf //example.org target_broken_symlink
+t_cmd 'target_broken_symlink:cleanup' '' rm target_broken_symlink
+
+t_args 'dest_broken_symlink:create' '' -s /foo/bar/dest_broken_symlink ./
t_args --exit=1 'dest_broken_symlink' "\
-ln: error: Destination 'dest_broken_symlink' already exists
-" -s //example.org dest_broken_symlink
-t_args 'dest_broken_symlink:force' '' -sf //example.org dest_broken_symlink
+ln: error: Destination './/dest_broken_symlink' already exists
+" -s /foo/bar/dest_broken_symlink ./
+t_args 'dest_broken_symlink:force' '' -sf /foo/bar/dest_broken_symlink ./
t_cmd 'dest_broken_symlink:cleanup' '' rm dest_broken_symlink