summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp96
-rw-r--r--src/corelib/io/qloggingregistry.cpp22
-rw-r--r--src/corelib/io/qloggingregistry_p.h1
-rw-r--r--src/corelib/io/qprocess_win.cpp3
-rw-r--r--src/corelib/io/qurl.cpp6
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(&registryMutex);
+
+ envRules = std::move(er);
+ qtConfigRules = std::move(qr);
+ configRules = std::move(cr);
if (!envRules.isEmpty() || !qtConfigRules.isEmpty() || !configRules.isEmpty()) {
- QMutexLocker locker(&registryMutex);
updateRules();
}
}
@@ -347,11 +353,11 @@ void QLoggingRegistry::setApiRules(const QString &content)
parser.setSection(QStringLiteral("Rules"));
parser.setContent(content);
- QMutexLocker locker(&registryMutex);
-
if (qtLoggingDebug())
debugMsg("Loading logging rules set by QLoggingCategory::setFilterRules ...");
+ const QMutexLocker locker(&registryMutex);
+
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());
}