Changeset 33


Ignore:
Timestamp:
Jun 17, 2009, 12:10:36 AM (11 years ago)
Author:
Dmitry A. Kuminov
Message:

corelib/io: QFileInfo::absoluteFilePath() and canonicalFilePath() could return incorrect results which would screw up qmake under some circumstances (in particular, debug_and_release in CONFIG).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/corelib/io/qfsfileengine_os2.cpp

    r21 r33  
    641641}
    642642
     643static bool isRelativePath(const QString &path)
     644{
     645    return !(path.startsWith(QLatin1Char('/'))
     646        || (path.length() >= 2
     647        && ((path.at(0).isLetter() && path.at(1) == QLatin1Char(':'))
     648        || (path.at(0) == QLatin1Char('/') && path.at(1) == QLatin1Char('/')))));                // drive, e.g. a:
     649}
     650
    643651QString QFSFileEngine::fileName(FileName file) const
    644652{
    645653    Q_D(const QFSFileEngine);
    646     if (file == BundleName) {
    647         return QString();
    648     } else if (file == BaseName) {
     654    if(file == BaseName) {
    649655        int slash = d->filePath.lastIndexOf(QLatin1Char('/'));
    650         if (slash != -1)
    651             return d->filePath.mid(slash + 1);
    652     } else if (file == PathName) {
     656        if(slash == -1) {
     657            int colon = d->filePath.lastIndexOf(QLatin1Char(':'));
     658            if(colon != -1)
     659                return d->filePath.mid(colon + 1);
     660            return d->filePath;
     661        }
     662        return d->filePath.mid(slash + 1);
     663    } else if(file == PathName) {
     664        if(!d->filePath.size())
     665            return d->filePath;
     666
    653667        int slash = d->filePath.lastIndexOf(QLatin1Char('/'));
    654         if (slash == -1)
    655             return QLatin1String(".");
    656         else if (!slash)
    657             return QLatin1String("/");
    658         return d->filePath.left(slash);
    659     } else if (file == AbsoluteName || file == AbsolutePathName) {
     668        if(slash == -1) {
     669            if(d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':'))
     670                return d->filePath.left(2);
     671            return QString::fromLatin1(".");
     672        } else {
     673            if(!slash)
     674                return QString::fromLatin1("/");
     675            if(slash == 2 && d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':'))
     676                slash++;
     677            return d->filePath.left(slash);
     678        }
     679    } else if(file == AbsoluteName || file == AbsolutePathName) {
    660680        QString ret;
    661         if (d->filePath.isEmpty() || !d->filePath.startsWith(QLatin1Char('/')))
    662             ret = QDir::currentPath();
    663         if (!d->filePath.isEmpty() && d->filePath != QLatin1String(".")) {
    664             if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/')))
    665                 ret += QLatin1Char('/');
    666             ret += d->filePath;
    667         }
    668         if (ret == QLatin1String("/"))
    669             return ret;
    670         bool isDir = ret.endsWith(QLatin1Char('/'));
    671         ret = QDir::cleanPath(ret);
    672         if (isDir)
    673             ret += QLatin1String("/");
     681
     682        if (!isRelativePath()) {
     683            if (d->filePath.size() > 2 && d->filePath.at(1) == QLatin1Char(':')
     684                && d->filePath.at(2) != QLatin1Char('/') || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt
     685                d->filePath.startsWith(QLatin1Char('/'))    // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt
     686                ) {
     687                char buf[PATH_MAX+1];
     688                strcpy(buf, QFile::encodeName(d->filePath).constData());
     689                _abspath(buf, buf, sizeof(buf));
     690                ret = QFile::decodeName(buf);
     691            } else {
     692                ret = d->filePath;
     693            }
     694        } else {
     695            ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + d->filePath);
     696        }
     697
     698        // The path should be absolute at this point.
     699        // From the docs :
     700        // Absolute paths begin with the directory separator "/"
     701        // (optionally preceded by a drive specification under Windows).
     702        if (ret.at(0) != QLatin1Char('/')) {
     703            Q_ASSERT(ret.length() >= 2);
     704            Q_ASSERT(ret.at(0).isLetter());
     705            Q_ASSERT(ret.at(1) == QLatin1Char(':'));
     706
     707            // Force uppercase drive letters.
     708            ret[0] = ret.at(0).toUpper();
     709        }
     710
    674711        if (file == AbsolutePathName) {
    675712            int slash = ret.lastIndexOf(QLatin1Char('/'));
    676             if (slash == -1)
    677                 return QDir::currentPath();
    678             else if (!slash)
    679                 return QLatin1String("/");
    680             return ret.left(slash);
     713            if (slash < 0)
     714                return ret;
     715            else if (ret.at(0) != QLatin1Char('/') && slash == 2)
     716                return ret.left(3);      // include the slash
     717            else
     718                return ret.left(slash > 0 ? slash : 1);
    681719        }
    682720        return ret;
    683     } else if (file == CanonicalName || file == CanonicalPathName) {
     721    } else if(file == CanonicalName || file == CanonicalPathName) {
    684722        if (!(fileFlags(ExistsFlag) & ExistsFlag))
    685723            return QString();
     
    695733        }
    696734        return ret;
    697     } else if (file == LinkName) {
     735    } else if(file == LinkName) {
    698736        if (d->isSymlink()) {
    699 #if defined(__GLIBC__) && !defined(PATH_MAX)
    700 #define PATH_CHUNK_SIZE 256
    701             char *s = 0;
    702             int len = -1;
    703             int size = PATH_CHUNK_SIZE;
    704 
    705             while (1) {
    706                 s = (char *) ::realloc(s, size);
    707                 if (s == 0) {
    708                     len = -1;
    709                     break;
     737            char buf[PATH_MAX+1];
     738            int len = readlink(d->nativeFilePath.constData(), buf, PATH_MAX);
     739            if (len > 0) {
     740                buf[len] = '\0';
     741                QString target = QDir::fromNativeSeparators(QFile::decodeName(QByteArray(buf)));
     742                QString ret;
     743                if (!::isRelativePath(target)) {
     744                    if (target.size() > 2 && target.at(1) == QLatin1Char(':')
     745                        && target.at(2) != QLatin1Char('/') || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt
     746                        target.startsWith(QLatin1Char('/'))    // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt
     747                        ) {
     748                        char buf[PATH_MAX+1];
     749                        strcpy(buf, QFile::encodeName(target).constData());
     750                        _abspath(buf, buf, sizeof(buf));
     751                        ret = QFile::decodeName(buf);
     752                    } else {
     753                        ret = target;
     754                    }
     755                } else {
     756                    if (S_ISDIR(d->st.st_mode)) {
     757                        QDir parent(d->filePath);
     758                        parent.cdUp();
     759                        ret = parent.path();
     760                        if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/')))
     761                            ret += QLatin1Char('/');
     762                    }
     763                    ret += target;
     764
     765                    if (::isRelativePath(ret)) {
     766                        if (!isRelativePath()) {
     767                            ret.prepend(d->filePath.left(d->filePath.lastIndexOf(QLatin1Char('/')))
     768                                        + QLatin1Char('/'));
     769                        } else {
     770                            ret.prepend(QDir::currentPath() + QLatin1Char('/'));
     771                        }
     772                    }
     773                    ret = QDir::cleanPath(ret);
     774                    if (ret.size() > 1 && ret.endsWith(QLatin1Char('/')))
     775                        ret.chop(1);
    710776                }
    711                 len = ::readlink(d->nativeFilePath.constData(), s, size);
    712                 if (len < 0) {
    713                     ::free(s);
    714                     break;
     777
     778                // The path should be absolute at this point.
     779                // From the docs :
     780                // Absolute paths begin with the directory separator "/"
     781                // (optionally preceded by a drive specification under Windows).
     782                if (ret.at(0) != QLatin1Char('/')) {
     783                    Q_ASSERT(ret.length() >= 2);
     784                    Q_ASSERT(ret.at(0).isLetter());
     785                    Q_ASSERT(ret.at(1) == QLatin1Char(':'));
     786
     787                    // Force uppercase drive letters.
     788                    ret[0] = ret.at(0).toUpper();
    715789                }
    716                 if (len < size) {
    717                     break;
    718                 }
    719                 size *= 2;
    720             }
    721 #else
    722             char s[PATH_MAX+1];
    723             int len = readlink(d->nativeFilePath.constData(), s, PATH_MAX);
    724 #endif
    725             if (len > 0) {
    726                 QString ret;
    727                 if (S_ISDIR(d->st.st_mode) && s[0] != '/') {
    728                     QDir parent(d->filePath);
    729                     parent.cdUp();
    730                     ret = parent.path();
    731                     if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/')))
    732                         ret += QLatin1Char('/');
    733                 }
    734                 s[len] = '\0';
    735                 ret += QFile::decodeName(QByteArray(s));
    736 #if defined(__GLIBC__) && !defined(PATH_MAX)
    737                 ::free(s);
    738 #endif
    739 
    740                 if (!ret.startsWith(QLatin1Char('/'))) {
    741                     if (d->filePath.startsWith(QLatin1Char('/'))) {
    742                         ret.prepend(d->filePath.left(d->filePath.lastIndexOf(QLatin1Char('/')))
    743                                     + QLatin1Char('/'));
    744                     } else {
    745                         ret.prepend(QDir::currentPath() + QLatin1Char('/'));
    746                     }
    747                 }
    748                 ret = QDir::cleanPath(ret);
    749                 if (ret.size() > 1 && ret.endsWith(QLatin1Char('/')))
    750                     ret.chop(1);
     790
    751791                return ret;
    752792            }
    753793        }
    754794        return QString();
     795    } else if(file == BundleName) {
     796        return QString();
    755797    }
    756798    return d->filePath;
     
    760802{
    761803    Q_D(const QFSFileEngine);
    762     return !(d->filePath.startsWith(QLatin1Char('/'))
    763         || (d->filePath.length() >= 2
    764         && ((d->filePath.at(0).isLetter() && d->filePath.at(1) == QLatin1Char(':'))
    765         || (d->filePath.at(0) == QLatin1Char('/') && d->filePath.at(1) == QLatin1Char('/')))));                // drive, e.g. a:
     804    return ::isRelativePath(d->filePath);
    766805}
    767806
Note: See TracChangeset for help on using the changeset viewer.