ls -FL

Version:

coreutils-6.7 (fixed in 6.8)

How to reproduce?

1. mkdir testls

2. touch origin.txt

    --- create a new file

3. ln -s origin.txt linkone.txt

/*in correct version*/

$ coreutils-6.8/src/ls -FRL

.:

linkone.txt   origin.txt

/*in wrong version*/

$ coreutils-6.7/src/ls -FRL

.:

linkone.txt@  origin.txt

Symptom:

The -L option, dereference, should follow the symbolic link to show the info of the target file, instead of still treating SL as SL. But in version 6.7 the ‘ls -FL’ still treats symbolic link file as a symbolic link file without dereferencing it. (printing the @).

Background:

-F, --classify
         append indicator (one of */=>@|) to entries

-L, --dereference
              when showing file information for a symbolic link, show informa-
              tion  for  the file the link references rather than for the link
              itself

So when -L is specified, the “@” should not be shown!

Root cause:

The ‘if’ condition controlling whether to dereference a symbolic link is messed up, causing the ‘ls’ not dereferencing it.

In the correct version, for symbolic file, because of type = symbolic_link  and dereference = DEREF_ALWAYS, the following if condition is true, and then this function follows the symbolic link file.  But for the wrong version, this if condition is false with the same value of type and dereference. Eventually, at the point of  the  print_file_name_and_frills().

ls.c

static uintmax_t

gobble_file (char const *name, enum filetype type, ino_t inode,

         bool command_line_arg, char const *dirname)

{

…...

 /* The if condition below controls whether to deference a sym link. Here, type == symbolic_link, dreference == DEREF_ALWAYS, print_inode == false. Therefore, in the buggy execution, the if below is evaluated as false (because print_inode == false). The patch simply loosened the condition, so this if can be evaluated as true. */

 if (command_line_arg

         || format_needs_stat

          || (type == directory && print_with_color)

-          || (print_inode

-             && (inode == NOT_AN_INODE_NUMBER

-                 /* When dereferencing symlinks, the inode must come from

-                    stat, but readdir provides the inode of lstat.  Command

-                    line dereferences are already taken care of by the above

-                    assertion that the inode number is not yet known.  */

-                 || (dereference == DEREF_ALWAYS

-                     && (type == symbolic_link || type == unknown))))

+          /* 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)

+             && (type == symbolic_link || type == unknown)

+             && (dereference == DEREF_ALWAYS

+                 || (command_line_arg && dereference != DEREF_NEVER)))

+          /* Command line dereferences are already taken care of by the above

+            assertion that the inode number is not yet known.  */

+          || (print_inode && inode == NOT_AN_INODE_NUMBER)

          || (format_needs_type

             && (type == unknown || command_line_arg

            || (type == normal && (indicator_style == classify    

            || (print_with_color

         && is_colored (C_EXEC))

            )))))

{

/* If ls falls here, it checks the type ‘dereference’, and if it is “DEREF_ALWAYS” (turned on by -L option), it will follow the symlink*/

        switch (dereference)

{

/* Uses stat to get the info of the target file. */

case DEREF_ALWAYS:

  err = stat (absolute_name, &f->stat);

  break;

case DEREF_COMMAND_LINE_ARGUMENTS:

        … …

}

}

…...            

}

Is there Error Message?

No

Can Errlog anticipate the error and put a magic error message?

No.