diff options
-rw-r--r-- | doc/coreutils.texi | 17 | ||||
-rw-r--r-- | src/ls.c | 5 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/d_type-check | 37 | ||||
-rw-r--r-- | tests/init.cfg | 10 | ||||
-rwxr-xr-x | tests/ls/stat-free-color | 54 |
6 files changed, 124 insertions, 1 deletions
diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 457ecabb2..b77d8dfda 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -7042,6 +7042,23 @@ Piping a colorized listing through a pager like @command{more} or @command{less} usually produces unreadable results. However, using @code{more -f} does seem to work. +@vindex LS_COLORS +@vindex SHELL @r{environment variable, and color} +Note that using the @option{--color} option may incur a noticeable +performance penalty when run in a directory with very many entries, +because the default settings require that @command{ls} @code{stat} every +single file it lists. +However, if you would like most of the file-type coloring +but can live without the other coloring options (e.g., +executable, orphan, sticky, other-writable, capability), use +@command{dircolors} to set the @env{LS_COLORS} environment variable like this, +@example +eval $(dircolors -p | perl -pe \ + 's/^((CAP|S[ET]|O[TR]|M|E)\w+).*/$1 00/' | dircolors -) +@end example +and on a @code{dirent.d_type}-capable file system, @command{ls} +will perform only one @code{stat} call per command line argument. + @item -F @itemx --classify @itemx --indicator-style=classify @@ -2740,7 +2740,10 @@ gobble_file (char const *name, enum filetype type, ino_t inode, /* When coloring a directory (we may know the type from direct.d_type), we have to stat it in order to indicate sticky and/or other-writable attributes. */ - || (type == directory && print_with_color) + || (type == directory && print_with_color + && (is_colored (C_OTHER_WRITABLE) + || is_colored (C_STICKY) + || is_colored (C_STICKY_OTHER_WRITABLE))) /* When dereferencing symlinks, the inode and type must come from stat, but readdir provides the inode and type of lstat. */ || ((print_inode || format_needs_type) diff --git a/tests/Makefile.am b/tests/Makefile.am index 6a8b79dcb..9bff3f00f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -10,6 +10,7 @@ EXTRA_DIST = \ CuSkip.pm \ CuTmpdir.pm \ check.mk \ + d_type-check \ envvar-check \ filefrag-extent-compare \ fiemap-capable \ @@ -426,6 +427,7 @@ TESTS = \ ls/rt-1 \ ls/stat-dtype \ ls/stat-failed \ + ls/stat-free-color \ ls/stat-free-symlinks \ ls/stat-vs-dirent \ ls/symlink-slash \ diff --git a/tests/d_type-check b/tests/d_type-check new file mode 100644 index 000000000..e40904907 --- /dev/null +++ b/tests/d_type-check @@ -0,0 +1,37 @@ +#!/usr/bin/python +# Exit 0 if "." has useful d_type information, else 1. +# Intended to exit 0 only on Linux/GNU systems. +import sys + +fail = 1 +try: + import ctypes + + (DT_UNKNOWN, DT_DIR,) = (0, 4,) + + class dirent(ctypes.Structure): + _fields_ = [ + ("d_ino", ctypes.c_long), + ("d_off", ctypes.c_long), + ("d_reclen", ctypes.c_ushort), + ("d_type", ctypes.c_ubyte), + ("d_name", ctypes.c_char*256)] + + direntp = ctypes.POINTER(dirent) + + # FIXME: find a way to hard-coding libc's so-name. + libc = ctypes.cdll.LoadLibrary("libc.so.6") + libc.readdir.restype = direntp + + dirp = libc.opendir(".") + if dirp: + ep = libc.readdir(dirp) + if ep: + name = ep.contents.d_name + if (name == "." or name == "..") and ep.contents.d_type == DT_DIR: + fail = 0 + +except: + pass + +sys.exit(fail) diff --git a/tests/init.cfg b/tests/init.cfg index 92f841f94..55d757175 100644 --- a/tests/init.cfg +++ b/tests/init.cfg @@ -322,6 +322,16 @@ fiemap_capable_() python $abs_srcdir/fiemap-capable "$@" } +# Skip the current test if "." lacks d_type support. +require_dirent_d_type_() +{ + python < /dev/null \ + || skip_test_ python missing: assuming no d_type support + + python $abs_srcdir/d_type-check \ + || skip_test_ requires d_type support +} + # Does the current (working-dir) file system support sparse files? require_sparse_support_() { diff --git a/tests/ls/stat-free-color b/tests/ls/stat-free-color new file mode 100755 index 000000000..d11c6f49c --- /dev/null +++ b/tests/ls/stat-free-color @@ -0,0 +1,54 @@ +#!/bin/sh +# Show that --color need not use stat, as long as we have d_type support. + +# Copyright (C) 2011 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, see <http://www.gnu.org/licenses/>. + +. "${srcdir=.}/init.sh"; path_prepend_ ../src +print_ver_ ls +require_strace_ stat +require_dirent_d_type_ + +ln -s nowhere dangle || framework_failure_ + +# Disable enough features via LS_COLORS so that ls --color +# can do its job without calling stat (other than the obligatory +# one-call-per-command-line argument). +cat <<EOF > color-without-stat || framework_failure_ +RESET 0 +DIR 01;34 +LINK 01;36 +FIFO 40;33 +SOCK 01;35 +DOOR 01;35 +BLK 40;33;01 +CHR 40;33;01 +ORPHAN 00 +SETUID 00 +SETGID 00 +CAPABILITY 00 +STICKY_OTHER_WRITABLE 00 +OTHER_WRITABLE 00 +STICKY 00 +EXEC 00 +MULTIHARDLINK 00 +EOF +eval $(dircolors -b color-without-stat) + +strace -o log -e stat,lstat ls --color=always . || fail=1 +n_lines=$(wc -l < log) +test $n_lines = 1 || fail=1 + +Exit $fail |