c++qtshortcut-fileqfileinfo

QFileInfo size() is returning shortcut TARGET size


I am scanning folder size like this:

qint64 dirSize = 0;
int fileCount = 0;

for(QDirIterator itDir(someDir, QDir::NoDotAndDotDot|QDir::Files|QDir::Hidden|QDir::System,
                       QDirIterator::Subdirectories);
    itDir.hasNext(); )
{
    itDir.next();
    dirSize += itDir.fileInfo().size();
    ++fileCount;
}

This appears to work fine.

However, I noticed that a folder containing Windows shortcuts (.lnk) is returning a much larger size than expected. The reason is that the sizes of the shortcut targets are being returned, rather than the sizes of the shortcut files themselves.

But according to QFileInfo documentation:

On Windows, symlinks (shortcuts) are .lnk files. The reported size() is that of the symlink (not the link's target) [...]

So my question is: what am I doing wrong here? How do I get the size of the shortcut file?


Solution

  • @Rob's answer works in most cases, but returns 0 when the the shortcut's target doesn't exist/is invalid.
    Taking a cue from that approach, you can also copy the shortcut and change the extension.

    So combining it all into a function (I'm assuming here that opening the target is cheaper/safer than copying the shortcut):

    qint64 getFileSize(const QString &path)
    {
        qint64 size = 0;
        QFileInfo fileInfo(path);
    
        if(fileInfo.isSymLink() && fileInfo.size() == QFileInfo(fileInfo.symLinkTarget()).size())
        {
            // Try this approach first
            QFile file(path);
            if(file.exists() && file.open(QIODevice::ReadOnly))
                size = file.size();
            file.close();
    
            // If that didn't work, try this
            if(size == 0)
            {
                QString tmpPath = path+".tmp";
                for(int i=2; QFileInfo().exists(tmpPath); ++i) // Make sure filename is unique
                    tmpPath = path+".tmp"+QString::number(i);
    
                if(QFile::copy(path, tmpPath))
                {
                    size = QFileInfo(tmpPath).size();
                    QFile::remove(tmpPath);
                }
            }
        }
        else size = fileInfo.size();
    
        return size;
    }