[Top][All Lists]
[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. */