bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [anonymous] [bugs #11124] ls stats symbolic link targets (fwd)


From: Jim Meyering
Subject: Re: [anonymous] [bugs #11124] ls stats symbolic link targets (fwd)
Date: Mon, 29 Nov 2004 15:32:00 +0100

address@hidden (Bob Proulx) wrote:
> I believe that ls --color will paint symlinks differently depending
> upon whether they are symlinks to files or symlinks to directories.
> Therefore the target of the symlink must be stat'd.

Well, actually, ls --color might have to stat symlinks to detect whether
a symlink has a target at all (depending on LS_COLORS settings).  If it
points to something that doesn't exist, then it gets the `ORPHAN' color
rather than the `LINK' one.  It also needs to know if a file is executable.

BTW, the colors are defined by dircolors.
Run dircolors --print-database for the list.

If you're concerned about extra stat calls, a compromise is to use ls's
(-p) --indicator-style=file-type option.  That's almost as good as -F,
in that it marks all files with their type suffix.  The only drawback
(or feature, depending on your perspective) is that it doesn't tell you
if a file's executable bit is set.  It'd have to call stat for that.

Hmm... I've just realized that the only reason (with ls's default
settings -- i.e., without an LS_COLORS envvar definition) that ls
lstat's a file is to see if it is executable.  And it does the
lstat even if there is no corresponding color indicator for C_EXEC.

So I've just fixed that.
With the patched ls, if you want ls --color to work, but without the
overhead of calling stat or lstat, then all you have to do is set your
LS_COLORS envvar to something that defines highlighting specs for none
of these three types of files:

  ORPHAN, MISSING, EXEC

Then you can set the LS_COLORS envvar like this:

eval `(dircolors --p|grep -Ev '^(EXEC|MISSING|ORPHAN) ';
       printf 'EXEC 0\nMISSING 0\nORPHAN 0\n')|dircolors -`

Then, ls --color will not stat every single file, yet still give
you highlighting, but not for files with the executable bit set.

Here's the patch I'm considering:

Index: src/ls.c
===================================================================
RCS file: /fetish/cu/src/ls.c,v
retrieving revision 1.368
diff -u -p -r1.368 ls.c
--- src/ls.c    19 Nov 2004 21:41:00 -0000      1.368
+++ src/ls.c    29 Nov 2004 09:15:15 -0000
@@ -537,7 +537,7 @@ static struct bin_str color_indicator[] 
     { LEN_STR_PAIR ("01;33") },                /* bd: Block device: bright 
yellow */
     { LEN_STR_PAIR ("01;33") },                /* cd: Char device: bright 
yellow */
     { 0, NULL },                       /* mi: Missing file: undefined */
-    { 0, NULL },                       /* or: Orphanned symlink: undefined */
+    { 0, NULL },                       /* or: Orphaned symlink: undefined */
     { LEN_STR_PAIR ("01;32") },                /* ex: Executable: bright green 
*/
     { LEN_STR_PAIR ("01;35") }         /* do: Door: bright magenta */
   };
@@ -985,6 +985,16 @@ free_pending_ent (struct pending *p)
   free (p);
 }
 
+static bool
+is_colored (enum indicator_no type)
+{
+  size_t len = color_indicator[type].len;
+  char const *s = color_indicator[type].string;
+  return ! (len == 0
+           || (len == 1 && strncmp (s, "0", 1) == 0)
+           || (len == 2 && strncmp (s, "00", 2) == 0));
+}
+
 static void
 restore_default_color (void)
 {
@@ -1104,9 +1114,9 @@ main (int argc, char **argv)
   if (print_with_color)
     {
       /* Avoid following symbolic links when possible.  */
-      if (color_indicator[C_ORPHAN].string != NULL
-         || (color_indicator[C_MISSING].string != NULL
-             && format == long_format))
+      if (is_colored (C_ORPHAN)
+         || is_colored (C_EXEC)
+         || (is_colored (C_MISSING) && format == long_format))
        check_symlink_color = true;
 
       /* If the standard output is a controlling terminal, watch out
@@ -2449,7 +2459,9 @@ gobble_file (const char *name, enum file
                                        highlighting files with the executable
                                        bit set even when options like -F are
                                        not specified.  */
-                                    || print_with_color)))))
+                                    || (print_with_color
+                                        && is_colored (C_EXEC))
+                                    )))))
 
     {
       /* `path' is the absolute pathname of this file.  */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]