diff options
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qfilesystemengine_unix.cpp | 96 | ||||
-rw-r--r-- | src/corelib/io/qloggingregistry.cpp | 22 | ||||
-rw-r--r-- | src/corelib/io/qloggingregistry_p.h | 1 | ||||
-rw-r--r-- | src/corelib/io/qprocess_win.cpp | 3 | ||||
-rw-r--r-- | src/corelib/io/qurl.cpp | 6 |
5 files changed, 84 insertions, 44 deletions
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 40eadfb3e6..3cb412e47c 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -553,45 +553,75 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM return data.hasFlags(what); } +// Note: if \a shouldMkdirFirst is false, we assume the caller did try to mkdir +// before calling this function. +static bool createDirectoryWithParents(const QByteArray &nativeName, bool shouldMkdirFirst = true) +{ + // helper function to check if a given path is a directory, since mkdir can + // fail if the dir already exists (it may have been created by another + // thread or another process) + const auto isDir = [](const QByteArray &nativeName) { + QT_STATBUF st; + return QT_STAT(nativeName.constData(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR; + }; + + if (shouldMkdirFirst && QT_MKDIR(nativeName, 0777) == 0) + return true; + if (errno == EEXIST) + return isDir(nativeName); + if (errno != ENOENT) + return false; + + // mkdir failed because the parent dir doesn't exist, so try to create it + int slash = nativeName.lastIndexOf('/'); + if (slash < 1) + return false; + + QByteArray parentNativeName = nativeName.left(slash); + if (!createDirectoryWithParents(parentNativeName)) + return false; + + // try again + if (QT_MKDIR(nativeName, 0777) == 0) + return true; + return errno == EEXIST && isDir(nativeName); +} + //static bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents) { QString dirName = entry.filePath(); - if (createParents) { - dirName = QDir::cleanPath(dirName); - for (int oldslash = -1, slash=0; slash != -1; oldslash = slash) { - slash = dirName.indexOf(QDir::separator(), oldslash+1); - if (slash == -1) { - if (oldslash == dirName.length()) - break; - slash = dirName.length(); - } - if (slash) { - const QByteArray chunk = QFile::encodeName(dirName.left(slash)); - if (QT_MKDIR(chunk.constData(), 0777) != 0) { - if (errno == EEXIST -#if defined(Q_OS_QNX) - // On QNX the QNet (VFS paths of other hosts mounted under a directory - // such as /net) mountpoint returns ENOENT, despite existing. stat() - // on the QNet mountpoint returns successfully and reports S_IFDIR. - || errno == ENOENT -#endif - ) { - QT_STATBUF st; - if (QT_STAT(chunk.constData(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR) - continue; - } - return false; - } - } - } + + // Darwin doesn't support trailing /'s, so remove for everyone + while (dirName.size() > 1 && dirName.endsWith(QLatin1Char('/'))) + dirName.chop(1); + + // try to mkdir this directory + QByteArray nativeName = QFile::encodeName(dirName); + if (QT_MKDIR(nativeName, 0777) == 0) return true; + if (!createParents) + return false; + + // we need the cleaned path in order to create the parents + // and we save errno just in case encodeName needs to load codecs + int savedErrno = errno; + bool pathChanged; + { + QString cleanName = QDir::cleanPath(dirName); + + // Check if the cleaned name is the same or not. If we were given a + // path with resolvable "../" sections, cleanPath will remove them, but + // this may change the target dir if one of those segments was a + // symlink. This operation depends on cleanPath's optimization of + // returning the original string if it didn't modify anything. + pathChanged = !dirName.isSharedWith(cleanName); + if (pathChanged) + nativeName = QFile::encodeName(cleanName); } -#if defined(Q_OS_DARWIN) // Mac X doesn't support trailing /'s - if (dirName.endsWith(QLatin1Char('/'))) - dirName.chop(1); -#endif - return (QT_MKDIR(QFile::encodeName(dirName).constData(), 0777) == 0); + + errno = savedErrno; + return createDirectoryWithParents(nativeName, pathChanged); } //static diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index b8d1919ee6..4f7bc95330 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -276,10 +276,11 @@ static QVector<QLoggingRule> loadRulesFromFile(const QString &filePath) */ void QLoggingRegistry::init() { + QVector<QLoggingRule> er, qr, cr; // get rules from environment const QByteArray rulesFilePath = qgetenv("QT_LOGGING_CONF"); if (!rulesFilePath.isEmpty()) - envRules = loadRulesFromFile(QFile::decodeName(rulesFilePath)); + er = loadRulesFromFile(QFile::decodeName(rulesFilePath)); const QByteArray rulesSrc = qgetenv("QT_LOGGING_RULES").replace(';', '\n'); if (!rulesSrc.isEmpty()) { @@ -287,7 +288,7 @@ void QLoggingRegistry::init() QLoggingSettingsParser parser; parser.setSection(QStringLiteral("Rules")); parser.setContent(stream); - envRules += parser.rules(); + er += parser.rules(); } const QString configFileName = QStringLiteral("qtlogging.ini"); @@ -296,17 +297,22 @@ void QLoggingRegistry::init() // get rules from Qt data configuration path const QString qtConfigPath = QDir(QLibraryInfo::location(QLibraryInfo::DataPath)).absoluteFilePath(configFileName); - qtConfigRules = loadRulesFromFile(qtConfigPath); + qr = loadRulesFromFile(qtConfigPath); #endif // get rules from user's/system configuration const QString envPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QString::fromLatin1("QtProject/") + configFileName); if (!envPath.isEmpty()) - configRules = loadRulesFromFile(envPath); + cr = loadRulesFromFile(envPath); + + const QMutexLocker locker(®istryMutex); + + envRules = std::move(er); + qtConfigRules = std::move(qr); + configRules = std::move(cr); if (!envRules.isEmpty() || !qtConfigRules.isEmpty() || !configRules.isEmpty()) { - QMutexLocker locker(®istryMutex); updateRules(); } } @@ -347,11 +353,11 @@ void QLoggingRegistry::setApiRules(const QString &content) parser.setSection(QStringLiteral("Rules")); parser.setContent(content); - QMutexLocker locker(®istryMutex); - if (qtLoggingDebug()) debugMsg("Loading logging rules set by QLoggingCategory::setFilterRules ..."); + const QMutexLocker locker(®istryMutex); + apiRules = parser.rules(); updateRules(); @@ -405,6 +411,8 @@ QLoggingRegistry *QLoggingRegistry::instance() /*! \internal Updates category settings according to rules. + + As a category filter, it is run with registryMutex held. */ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) { diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h index 5197da1ba4..23740c4955 100644 --- a/src/corelib/io/qloggingregistry_p.h +++ b/src/corelib/io/qloggingregistry_p.h @@ -129,6 +129,7 @@ private: QMutex registryMutex; + // protected by mutex: QVector<QLoggingRule> qtConfigRules; QVector<QLoggingRule> configRules; QVector<QLoggingRule> envRules; diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index fcdf13fddb..aa69e9e1db 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -844,7 +844,8 @@ static bool startDetachedUacPrompt(const QString &programIn, const QStringList & SHELLEXECUTEINFOW shellExecuteExInfo; memset(&shellExecuteExInfo, 0, sizeof(SHELLEXECUTEINFOW)); shellExecuteExInfo.cbSize = sizeof(SHELLEXECUTEINFOW); - shellExecuteExInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE | SEE_MASK_FLAG_NO_UI; + shellExecuteExInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE | SEE_MASK_FLAG_NO_UI | SEE_MASK_CLASSNAME; + shellExecuteExInfo.lpClass = L"exefile"; shellExecuteExInfo.lpVerb = L"runas"; const QString program = QDir::toNativeSeparators(programIn); shellExecuteExInfo.lpFile = reinterpret_cast<LPCWSTR>(program.utf16()); diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index a6372b75f6..18ad59f1cb 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -4169,10 +4169,10 @@ QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirecto return url; } - QUrl url = QUrl(trimmedString, QUrl::TolerantMode); + QUrl url = QUrl(userInput, QUrl::TolerantMode); // Check both QUrl::isRelative (to detect full URLs) and QDir::isAbsolutePath (since on Windows drive letters can be interpreted as schemes) - if (url.isRelative() && !QDir::isAbsolutePath(trimmedString)) { - QFileInfo fileInfo(QDir(workingDirectory), trimmedString); + if (url.isRelative() && !QDir::isAbsolutePath(userInput)) { + QFileInfo fileInfo(QDir(workingDirectory), userInput); if ((options & AssumeLocalFile) || fileInfo.exists()) return QUrl::fromLocalFile(fileInfo.absoluteFilePath()); } |