du -a -L

Version:

coreutils-8.5 (fixed in 8.6)

How to reproduce?

1. create a directory that includes a normal file and also its correspondent symbolic link file.

2. use the command  du -a -L

Symptom:

Incorrect result.

in version 8.5 the ‘du -a -L’ will blindly account the occupied space twice for the original file and its correspondent symbolic link file.

Root cause:

Developer didn’t handle the case of symbolic linked object.

In the buggy version, the symbolic linked object is processed the same way as normal object, resulting in counting the space usage twice.

In the correct version, they used a hash table to keep track of which inode has already been processed. Thus they can avoid processing the symbolicly linked object twice.

Detail:

In version 8.6, developer added the new hash function set called di_set in lib to record inode visited. For symbolic link file, it has same inode and dev (variable st_ino and st_dev) with link target.

/* process_file is to count and print disk space usage. */

static bool  process_file (FTS *fts, FTSENT *ent)

{

 …..

  /* The following logic is newly added. So that if the inode has

     been processed before, they will simply return without

     further processing. hash_ins is to check if the inode

     (st_ino) and dev (st_dev) pair has been visited before. */

 +     if (excluded || (! opt_count_all

 +        && (hash_all || (! S_ISDIR (sb->st_mode) && 1 < sb->st_nlink))

 +       && ! hash_ins (sb->st_ino, sb->st_dev)))

 +        {

 +         …...

 +         return true;

 +        }

     

  /* In the buggy version, for symbolic files it just fell through... */

           switch (info)

           {

           case FTS_D:

             return true;

           case FTS_ERR:

             .. ..

           case FTS_DC:  

            .. ..

     /* In the buggy execution, it falls into

        the ‘default’ case with info = “FTS_SL” -- symbolic link.

        It would be important if we can log at the default case. */                  

     default:

         ok = true;

         break;

           }

         …...

   

}

Is there Error Message?

No

Can Errlog print an error message?

Yes. In the default case of the switch statement in process_files above, Errlog will print an error and print the switch variable (info == FTS_SL), indicating it’s symbolic link.

This information will be very helpful!