I expect to write an accompanying strace-using test case before pushing
the patch below:

For reference, to demonstrate that stat-free use of ls --color,
you have to disable all of these via dircolors/LS_COLORS:

  CAPABILITY
  EXEC
  MISSING
  ORPHAN
  OTHER_WRITABLE
  SETGID
  SETUID
  STICKY
  STICKY_OTHER_WRITABLE

Here's one way to set LS_COLORS:

  eval $(dircolors -p|perl -pe \
                        's/^((CAP|S[ET]|O[TR]|M|E)\w+).*/$1 00/'|dircolors -)

Then, strace -e file ./ls SOME_DIRECTORY
should show exactly one stat call and no lstat call.

>From b456a2e680b1969ddac61a770417493b52973dc0 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyer...@redhat.com>
Date: Wed, 11 May 2011 17:13:53 +0200
Subject: [PATCH] ls: allow stat-free use of --color

Even on a system with d_type support, the default use of --color
makes ls stat every file in order to be able to honor settings like
EXEC, STICKY, ORPHAN, SETUID, etc. because those settings require
information that is not provided by dirent.d_type.  However, if
for a potentially large performance gain, you are willing to disable
those setting, you can now make ls --color give type-related coloring
and perform no stat calls at all (other than the unavoidable call-per-
command-line argument).  Before this change, even with all of those
attributes disabled, ls --color would still stat every directory.
* src/ls.c (gobble_file): With --color, don't stat a
non-command-line-specified directory when no directory-coloring
attribute is enabled.
Prompted by a query from Josef Bacik.
---
 src/ls.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/src/ls.c b/src/ls.c
index 4262923..54876ce 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -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)
--
1.7.5.1.354.g761178

Reply via email to