]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
install: dereference source symlinks when comparing
authorPádraig Brady <P@draigBrady.com>
Mon, 19 Aug 2024 11:43:09 +0000 (12:43 +0100)
committerPádraig Brady <P@draigBrady.com>
Mon, 19 Aug 2024 13:47:07 +0000 (14:47 +0100)
* 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

NEWS
src/install.c
tests/install/install-C.sh

diff --git a/NEWS b/NEWS
index 65cc3fde00e39cc7c10b66869154851ffb35a7cf..e1d3f82d1716d7444d9cacc937b51fb6bc952633 100644 (file)
--- 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
index 939db9cd41c5fb75f41ea63acf782f8319afb43a..85f2d9e110a13a5ab231663454a497ad960724b2 100644 (file)
@@ -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)
index a6b332e14ca3e9df78acb52e2a82b2de1f5007e0..2751fb0b6c0cc021b6197bb1577433d652aa5eca 100755 (executable)
@@ -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