aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2024-08-19 12:43:09 +0100
committerPádraig Brady <P@draigBrady.com>2024-08-19 14:47:07 +0100
commit403cb48413519396b7df0943cb5fbab5b3d5b3e2 (patch)
tree47c46d5fe4fc90aca7524652758451f0be4f2ab3
parentmaint: adjust to recent removal of verror.c (diff)
downloadcoreutils-403cb48413519396b7df0943cb5fbab5b3d5b3e2.tar.gz
coreutils-403cb48413519396b7df0943cb5fbab5b3d5b3e2.zip
install: dereference source symlinks when comparing
* NEWS: Mention the change in behavior. * src/install.c (need_copy): s/lstat/stat/ for the source. * tests/install/install-C.sh: Add test cases (and improve existing test case which wan't valid due to the existing non standard modes on test files). Addresses https://bugs.gnu.org/72707
-rw-r--r--NEWS3
-rw-r--r--src/install.c2
-rwxr-xr-xtests/install/install-C.sh13
3 files changed, 15 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index 65cc3fde0..e1d3f82d1 100644
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,9 @@ GNU coreutils NEWS -*- outline -*-
** Changes in behavior
+ install -C now dereferences symlink sources when comparing,
+ rather than always treating as different and performing the copy.
+
ls's -f option now simply acts like -aU, instead of also ignoring
some earlier options. For example 'ls -fl' and 'ls -lf' are now
equivalent because -f no longer ignores an earlier -l. The new
diff --git a/src/install.c b/src/install.c
index 939db9cd4..85f2d9e11 100644
--- a/src/install.c
+++ b/src/install.c
@@ -177,7 +177,7 @@ need_copy (char const *src_name, char const *dest_name,
return true;
/* compare files using stat */
- if (lstat (src_name, &src_sb) != 0)
+ if (stat (src_name, &src_sb) != 0)
return true;
if (fstatat (dest_dirfd, dest_relname, &dest_sb, AT_SYMLINK_NOFOLLOW) != 0)
diff --git a/tests/install/install-C.sh b/tests/install/install-C.sh
index a6b332e14..2751fb0b6 100755
--- a/tests/install/install-C.sh
+++ b/tests/install/install-C.sh
@@ -78,9 +78,18 @@ compare out out_installed_second || fail=1
ginstall -Cv -m$mode3 a b > out || fail=1
compare out out_installed_second || fail=1
-# files are not regular files
+# non regular files
+ginstall -v -m$mode1 a b > out || fail=1 # reset to regular mode
+compare out out_installed_second || fail=1
+# symlink source is always dereferenced (and so regular here)
+ginstall -v -m$mode1 a d > out || fail=1 # create regular dest
+echo "'a' -> 'd'" > out_installed_first_ad || framework_failure_
+compare out out_installed_first_ad || fail=1
ln -s a c || framework_failure_
-ln -s b d || framework_failure_
+ginstall -Cv -m$mode1 c d > out || fail=1
+compare out out_empty || fail=1
+# symlink dest never created by install so deemed non regular
+ln -nsf b d || framework_failure_
ginstall -Cv -m$mode1 c d > out || fail=1
echo "removed 'd'
'c' -> 'd'" > out_installed_second_cd