Ignore:
Timestamp:
Dec 1, 2009, 2:24:09 AM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

corelib/io: Fixed: QDir::midir()/mkpath()/rmdir()/rmpath() didn't properly handle relative paths and UNC paths which could result into a false failure to create a requested path or creating it at the wrong location.

File:
1 edited

Legend:

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

    r365 r367  
    138138}
    139139
     140
     141
     142
     143
     144
     145
     146
     147
     148
     149
     150
     151
     152
     153
     154
     155
     156
     157
     158
     159
     160
     161
     162
     163
     164
     165
     166
     167
    140168/*!
    141169    \internal
     
    401429bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
    402430{
    403     QString dirName = name;
     431    // Note: according to what I see in implementations of this function on
     432    // other platforms, it expects name to be the absolute path (since no
     433    // member variables of this class are used in there). Thus, assert.
     434    Q_ASSERT(!::isRelativePath(name) && !::isNotReallyAbsolutePath(name));
     435    if (::isRelativePath(name) || ::isNotReallyAbsolutePath(name))
     436        return false;
     437
     438    QString dirName = QDir::toNativeSeparators(QDir::cleanPath(name));
    404439    if (createParentDirectories) {
    405         dirName = QDir::cleanPath(dirName);
    406         for(int oldslash = -1, slash=0; slash != -1; oldslash = slash) {
    407             slash = dirName.indexOf(QDir::separator(), oldslash+1);
    408             if (slash == -1) {
    409                 if (oldslash == dirName.length())
    410                     break;
    411                 slash = dirName.length();
     440        int sep = -1;
     441        if (dirName.startsWith(QLatin1String("\\\\"))) {
     442            // don't attempt to create a share on the server
     443            sep = dirName.indexOf(QLatin1Char('\\'), 2);
     444            if (sep)
     445                sep = dirName.indexOf(QLatin1Char('\\'), sep + 1);
     446            if (sep < 0) // "\\server" or "\\server\share"?
     447                return false;
     448        } else if (dirName.at(1) == QLatin1Char(':')) {
     449            // don't attempt to create the root dir on drive
     450            sep = 2;
     451        }
     452        while (sep < dirName.length()) {
     453            sep = dirName.indexOf(QLatin1Char('\\'), sep + 1);
     454            if (sep < 0)
     455                sep = dirName.length();
     456            QByteArray chunk = QFile::encodeName(dirName.left(sep));
     457            QT_STATBUF st;
     458            if (QT_STAT(chunk, &st) != -1) {
     459                if ((st.st_mode & S_IFMT) != S_IFDIR)
     460                    return false;
     461            } else if (::mkdir(chunk, 0777) != 0) {
     462                    return false;
    412463            }
    413             if (slash) {
    414                 QByteArray chunk = QFile::encodeName(dirName.left(slash));
    415                 QT_STATBUF st;
    416                 if (QT_STAT(chunk, &st) != -1) {
    417                     if ((st.st_mode & S_IFMT) != S_IFDIR)
    418                         return false;
    419                 } else if (::mkdir(chunk, 0777) != 0) {
    420                         return false;
    421                 }
    422             }
    423464        }
    424465        return true;
     
    429470bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
    430471{
    431     QString dirName = name;
     472    // Note: according to what I see in implementations of this function on
     473    // other platforms, it expects name to be the absolute path (since no
     474    // member variables of this class are used in there). Thus, assert.
     475    Q_ASSERT(!::isRelativePath(name) && !::isNotReallyAbsolutePath(name));
     476    if (::isRelativePath(name) || ::isNotReallyAbsolutePath(name))
     477        return false;
     478
     479    QString dirName = QDir::toNativeSeparators(QDir::cleanPath(name));
    432480    if (recurseParentDirectories) {
    433         dirName = QDir::cleanPath(dirName);
    434         for(int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
    435             QByteArray chunk = QFile::encodeName(dirName.left(slash));
     481        int lastSep = -1;
     482        if (dirName.startsWith(QLatin1String("\\\\"))) {
     483            // don't attempt to delete a share on the server
     484            lastSep = dirName.indexOf(QLatin1Char('\\'), 2);
     485            if (lastSep)
     486                lastSep = dirName.indexOf(QLatin1Char('\\'), lastSep + 1);
     487            if (lastSep < 0) // "\\server" or "\\server\share"?
     488                return false;
     489        } else if (dirName.at(1) == QLatin1Char(':')) {
     490            // don't attempt to delete the root dir on the drive
     491            lastSep = 2;
     492        }
     493        int sep = dirName.length();
     494        while (sep > lastSep) {
     495            QByteArray chunk = QFile::encodeName(dirName.left(sep));
    436496            QT_STATBUF st;
    437497            if (QT_STAT(chunk, &st) != -1) {
     
    439499                    return false;
    440500                if (::rmdir(chunk) != 0)
    441                     return oldslash != 0;
     501                    return ;
    442502            } else {
    443503                return false;
    444504            }
    445             slash = dirName.lastIndexOf(QDir::separator(), oldslash-1);
     505            s1);
    446506        }
    447507        return true;
     
    646706    }
    647707    return ret;
    648 }
    649 
    650 static bool isRelativePath(const QString &path)
    651 {
    652     // On OS/2, paths like "A:bbb.txt" and "\ccc.dat" are not absolute (because
    653     // they may lead to different locations depending on where we are). However,
    654     // fixing this function will break an unfixable amount of invalid code in Qt
    655     // and qmake (just search for isRelativePath in there) so that we have to
    656     // live with it... See also QDir::absoluteFilePath() and
    657     // isNotReallyAbsolutePath() below.
    658 
    659     return !(path.startsWith(QLatin1Char('/')) || // "\ccc.dat" or "\\server\share..."
    660              (path.length() >= 2 && path.at(0).isLetter() && // "A:bbb..." or "A:\bbb..."
    661               path.at(1) == QLatin1Char(':')));
    662 }
    663 
    664 static bool isNotReallyAbsolutePath(const QString &path)
    665 {
    666     // see isRelativePath(). Intended to detect a false absolute case when
    667     // isRelativePath() returns true
    668 
    669     QChar ch0, ch1, ch2;
    670     if (path.length()) ch0 = path.at(0);
    671     if (path.length() > 1) ch1 = path.at(1);
    672     if (path.length() > 2) ch2 = path.at(2);
    673     return ((ch0 == QLatin1Char('/') && ch1 != QLatin1Char('/')) || // "\ccc.dat"
    674             (ch0.isLetter() && ch1 == QLatin1Char(':') && // "A:bbb.txt" (but not A:)
    675              !ch2.isNull() && ch2 != QLatin1Char('/')));
    676708}
    677709
Note: See TracChangeset for help on using the changeset viewer.