Bug 159861

Summary: d_type optimisation is broken for symlinks
Product: [Frameworks and Libraries] kdelibs Reporter: Adam Sampson <ats-kdebugs>
Component: generalAssignee: kdelibs bugs <kdelibs-bugs>
Status: RESOLVED DUPLICATE    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Compiled Sources   
OS: Linux   
Latest Commit: Version Fixed In:
Attachments: Fix for this problem in kdelibs (but please check elsewhere too!)

Description Adam Sampson 2008-03-25 23:30:43 UTC
Version:            (using KDE 4.0.2)
Installed from:    Compiled From Sources
Compiler:          GCC 4.2.3 
OS:                Linux

A couple of libraries in kdelibs make use of the d_type field in struct dirent on systems such as Linux; this avoids the significant overhead of a stat call for each directory entry. For examples, see kdecore/kernel/kstandarddirs.cpp or kded/vfolder_menu.cpp, each of which has two instances of code like the following:

#ifdef HAVE_DIRENT_D_TYPE
            isDir = ep->d_type == DT_DIR;
            isReg = ep->d_type == DT_REG;

            if (ep->d_type == DT_UNKNOWN)
#endif
            {
                KDE_struct_stat buff;
                if ( KDE_stat( QFile::encodeName(pathfn), &buff ) != 0 ) {
                    ...
                }
                isReg = S_ISREG (buff.st_mode);
                isDir = S_ISDIR (buff.st_mode);
            }

However, this code behaves incorrectly when the directory entry is a symlink -- in which case readdir returns ep->d_type == DT_LNK, but stat will reference the symlink and S_ISREG will return true.

The result of this is that kbuildsyscoca (and anything else using this code) will silently ignore files and directories that are symlinks if kdelibs was built with HAVE_DIRENT_D_TYPE. This makes KDE4 not work at all if it's installed using a symlink-based packaging system such as stow, since (for example) it won't be able to resolve any MIME types.

The fix I've applied is to change the if test to:

            if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)

... so that when it finds a symlink, it'll fall back to using stat to dereference it. This makes kbuildsycoca work properly again for me.

Since I found the same code in four places in kdelibs, it doesn't seem entirely unreasonable that it might have been copied elsewhere too; it would probably be worth scanning the entire repository for "->d_type" and checking the same bug doesn't exist elsewhere.
Comment 1 Adam Sampson 2008-03-25 23:31:29 UTC
Created attachment 24052 [details]
Fix for this problem in kdelibs (but please check elsewhere too!)
Comment 2 David Faure 2008-03-26 12:19:54 UTC
Checked elsewhere: no other use of d_type: http://lxr.kde.org/ident?i=d_type

Will apply.

*** This bug has been marked as a duplicate of 150307 ***