From: Pádraig Brady
Date: Mon, 19 Aug 2024 11:43:09 +0000 (+0100) Subject: install: dereference source symlinks when comparing X-Git-Tag: v9.6~176 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=403cb48413519396b7df0943cb5fbab5b3d5b3e2;p=thirdparty%2Fcoreutils.git 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 --- diff --git a/NEWS b/NEWS index 65cc3fde00..e1d3f82d17 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 939db9cd41..85f2d9e110 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 a6b332e14c..2751fb0b6c 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