From 0a744370bb9a58b023d518bf4f32a5cb36929138 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sun, 15 Jul 2007 22:13:16 +0200 Subject: [PATCH] ls --color: Don't stat symlinks when neither ORPHAN nor MISSING attribute has a color. * src/ls.c (main): Don't set check_symlink_color when C_EXEC is colored, unless ln=target (aka color_symlink_as_referent) is set. (gobble_file): Set f->linkok = true also when !check_symlink_color. http://thread.gmane.org/gmane.comp.gnu.coreutils.bugs/10608/focus=10927 Reported by Jeremy Maitin-Shepard. * tests/strace: New file, contents extracted from... * tests/mv/atomic: ...here. Source strace. * tests/ls/stat-free-symlinks: New file. Test for the above. Use strace to ensure that in this corner case, ls does not call stat. * tests/ls/Makefile.am (TESTS): Add stat-free-symlinks. * tests/Makefile.am (EXTRA_DIST): Add strace. --- ChangeLog | 16 ++++++++++ THANKS | 1 + src/ls.c | 8 ++++- tests/Makefile.am | 1 + tests/ls/Makefile.am | 1 + tests/ls/stat-free-symlinks | 72 +++++++++++++++++++++++++++++++++++++++++++++ tests/mv/atomic | 15 ++-------- tests/strace | 30 +++++++++++++++++++ 8 files changed, 130 insertions(+), 14 deletions(-) create mode 100755 tests/ls/stat-free-symlinks create mode 100644 tests/strace diff --git a/ChangeLog b/ChangeLog index 5da6380..99cbd62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2007-07-15 Jim Meyering + + ls --color: Don't stat symlinks when neither ORPHAN nor MISSING + attribute has a color. + * src/ls.c (main): Don't set check_symlink_color when C_EXEC is + colored, unless ln=target (aka color_symlink_as_referent) is set. + (gobble_file): Set f->linkok = true also when !check_symlink_color. + http://thread.gmane.org/gmane.comp.gnu.coreutils.bugs/10608/focus=10927 + Reported by Jeremy Maitin-Shepard. + * tests/strace: New file, contents extracted from... + * tests/mv/atomic: ...here. Source strace. + * tests/ls/stat-free-symlinks: New file. Test for the above. + Use strace to ensure that in this corner case, ls does not call stat. + * tests/ls/Makefile.am (TESTS): Add stat-free-symlinks. + * tests/Makefile.am (EXTRA_DIST): Add strace. + 2007-07-14 Jim Meyering Remove long-deprecated options. diff --git a/THANKS b/THANKS index 7d590b1..601ca8f 100644 --- a/THANKS +++ b/THANKS @@ -229,6 +229,7 @@ Jeff Moore jbm@mordor.com Jeff Sheinberg jeff@bsrd.net Jens Elkner elkner@imsgroup.de Jens Schmidt jms@jsds.hamburg.com +Jeremy Maitin-Shepard jbms@cmu.edu Jerome Abela abela@hsc.fr Jérôme Zago bug-coreutils-ml@agt-the-walker.net Jesse Kornblum kornblum@usna.edu diff --git a/src/ls.c b/src/ls.c index 751dc3d..204341c 100644 --- a/src/ls.c +++ b/src/ls.c @@ -1168,7 +1168,7 @@ main (int argc, char **argv) { /* Avoid following symbolic links when possible. */ if (is_colored (C_ORPHAN) - || is_colored (C_EXEC) + || (is_colored (C_EXEC) && color_symlink_as_referent) || (is_colored (C_MISSING) && format == long_format)) check_symlink_color = true; @@ -2713,6 +2713,12 @@ gobble_file (char const *name, enum filetype type, ino_t inode, free (linkname); } + /* When not distinguishing types of symlinks, pretend we know that + it is stat'able, so that it will be colored as a regular symlink, + and not as an orphan. */ + if (S_ISLNK (f->stat.st_mode) && !check_symlink_color) + f->linkok = true; + if (S_ISLNK (f->stat.st_mode)) f->filetype = symbolic_link; else if (S_ISDIR (f->stat.st_mode)) diff --git a/tests/Makefile.am b/tests/Makefile.am index 682a52c..5606839 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -19,6 +19,7 @@ EXTRA_DIST = \ expensive group-names input-tty lang-default mk-script \ other-fs-tmpdir priv-check \ rwx-to-mode sample-test selinux setgid-check sparse-file \ + strace \ umask-check very-expensive ## N O T E :: Please do not add new tests/ directories. diff --git a/tests/ls/Makefile.am b/tests/ls/Makefile.am index ecd018e..45ca9fe 100644 --- a/tests/ls/Makefile.am +++ b/tests/ls/Makefile.am @@ -18,6 +18,7 @@ # 02110-1301, USA. TESTS = \ + stat-free-symlinks \ nameless-uid \ color-dtype-dir \ stat-failed \ diff --git a/tests/ls/stat-free-symlinks b/tests/ls/stat-free-symlinks new file mode 100755 index 0000000..78d91c9 --- /dev/null +++ b/tests/ls/stat-free-symlinks @@ -0,0 +1,72 @@ +#!/bin/sh +# ensure that ls does not stat a symlink in an unusual case + +# Copyright (C) 2007 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +if test "$VERBOSE" = yes; then + set -x + ls --version +fi + +. $srcdir/../envvar-check +. $srcdir/../strace + +pwd=`pwd` +t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$ +trap 'status=$?; cd "$pwd" && chmod -R u+rwx $t0 && rm -rf $t0 && exit $status' 0 +trap '(exit $?); exit $?' 1 2 13 15 + +framework_failure=0 +mkdir -p $tmp || framework_failure=1 +cd $tmp || framework_failure=1 + +touch x || framework_failure=1 +chmod a+x x || framework_failure=1 +ln -s x link-to-x || framework_failure=1 + +if test $framework_failure = 1; then + echo "$0: failure in testing framework" 1>&2 + (exit 1); exit 1 +fi + +fail=0 + +# ls from coreutils 6.9 would unnecessarily stat a symlink in an unusual case: +# When not coloring orphan and missing entries, and without ln=target, +# ensure that ls -F (or -d, or -l: i.e., when not dereferencing) +# does not stat a symlink to directory, and does still color that +# symlink and an executable file properly. + +LS_COLORS='or=0:mi=0:ex=01;32:ln=01;35' \ + strace -qe stat ls -F --color=always x link-to-x > out 2> err || fail=1 + +# With coreutils 6.9 and earlier, this file would contain a +# line showing ls had called stat on "x". +test -s err && fail=1 + +# Check that output is colorized, as requested, too. +{ + printf '\e[0m\e[01;35mlink-to-x\e[0m@\n' + printf '\e[01;32mx\e[0m*\n' + printf '\e[m' +} > exp || fail=1 + +cmp out exp || fail=1 +test $fail = 1 && diff out exp 2> /dev/null + +(exit $fail); exit $fail diff --git a/tests/mv/atomic b/tests/mv/atomic index 2b49fde..69374b9 100755 --- a/tests/mv/atomic +++ b/tests/mv/atomic @@ -23,6 +23,8 @@ if test "$VERBOSE" = yes; then mv --version fi +. $srcdir/../strace + pwd=`pwd` t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$ trap 'status=$?; cd "$pwd" && chmod -R u+rwx $t0 && rm -rf $t0 && exit $status' 0 @@ -48,19 +50,6 @@ if test $framework_failure = 1; then (exit 1); exit 1 fi -# Skip this test on systems without strace. -strace -V < /dev/null > ver 2>&1 || skip=1 -if test "$skip" = 1; then - echo "$0: no strace program, so skipping this test" 1>&2 - (exit 77); exit 77 -fi - -strace -qe unlink echo > /dev/null 2>&1 || skip=1 -if test "$skip" = 1; then - echo "$0: strace doesn't work, so skipping this test" 1>&2 - (exit 77); exit 77 -fi - fail=0 strace -qe unlink mv -T s1 s2 > out 2>&1 || fail=1 diff --git a/tests/strace b/tests/strace new file mode 100644 index 0000000..0bb022a --- /dev/null +++ b/tests/strace @@ -0,0 +1,30 @@ +# Skip the current test if strace is not available or doesn't work. + +# Copyright (C) 2007 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +strace -V < /dev/null > /dev/null 2>&1 || +{ + echo "$0: no strace program, so skipping this test" 1>&2 + (exit 77); exit 77 +} + +strace -qe unlink echo > /dev/null 2>&1 || +{ + echo "$0: strace doesn't work, so skipping this test" 1>&2 + (exit 77); exit 77 +} -- 2.7.4