[Interest] QDir::entry(Info)List on macos

Henry Skoglund fromqt at tungware.se
Fri Nov 16 00:40:00 CET 2018


On 2018-11-15 17:07, Thiago Macieira wrote:
> On Thursday, 15 November 2018 05:54:22 PST Manner RĂ³bert wrote:
>> Hope it is useful for someone. To be honest, I always imagined that if
>> everyone would use UTF-8 life would be much better, now I'm unsure
> 
> Blame Apple for deciding to use an uncommon normalisation back in the day for
> HFS. The HFS stores filenames in NFD, even if you type NFC and that's what you
> do in Terminal.app. But APFS doesn't convert.
> 
> Anyway, this is an open bug that needs a fix. I can't fix it because I don't
> have access to any Mac with APFS (my 2011 Mac Mini is running HFS).
> 

Hi, couldn't resist looking into this bug (my 2012 MBP has 10.14 with APFS):

The problem I think is that the encodeName(decodeName(filename)) if 
statement in qfilesystemiterator_unix.cpp is lossy; the incoming 
direntries can be either encoded as NFC (e.g. files created in Terminal) 
or NFD (files created via a Qt App or Finder), but the 
Q_OS_DARWIN-flavored QFile::encodeName() function is hardwired to use 
NormalizationForm_D only, that's why the NFC types of direntries get 
tossed out :-(

So one solution could be to check for both NFC- and NFD-flavored 
direntries that matches, say something like:

bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, 
QFileSystemMetaData &metaData)
{
     if (!dir)
         return false;

     for (;;) {
         dirEntry = QT_READDIR(dir);

         if (dirEntry) {
             // process entries with correct UTF-8 names only
             QString nfc = QFile::decodeName(dirEntry->d_name);  // (any 
NFDs are now converted to NFCs)

             if ((nfc.normalized(QString::NormalizationForm_C).toUtf8() 
== dirEntry->d_name) ||
                 (nfc.normalized(QString::NormalizationForm_D).toUtf8() 
== dirEntry->d_name)) {
                 fileEntry = QFileSystemEntry(nativePath + 
QByteArray(dirEntry->d_name), QFileSystemEntry::FromNativePath());
                 metaData.fillFromDirEnt(*dirEntry);
                 return true;
             }
         } else {
             break;
         }
     }

     lastError = errno;
     return false;
}

Note: this is written without any testing or compiling, just an idea!
Rgrds Henry




More information about the Interest mailing list