summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qfiledevice.cpp2
-rw-r--r--src/corelib/io/qfileselector.cpp15
-rw-r--r--src/corelib/io/qfsfileengine.cpp46
-rw-r--r--src/corelib/io/qlockfile_p.h2
-rw-r--r--src/corelib/io/qlockfile_unix.cpp42
-rw-r--r--src/corelib/io/qsettings.cpp8
-rw-r--r--src/corelib/io/qurl.cpp53
-rw-r--r--src/corelib/io/qwinoverlappedionotifier.cpp2
8 files changed, 104 insertions, 66 deletions
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index 0817dbec41..8ea2206e6b 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -566,7 +566,7 @@ qint64 QFileDevice::writeData(const char *data, qint64 len)
char *writePointer = d->writeBuffer.reserve(len);
if (len == 1)
*writePointer = *data;
- else
+ else if (len)
::memcpy(writePointer, data, len);
return len;
}
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index 9cca3793a2..a84a03837d 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -229,9 +229,9 @@ QString QFileSelector::select(const QString &filePath) const
static bool isLocalScheme(const QString &file)
{
- bool local = file == QStringLiteral("qrc");
+ bool local = file == QLatin1String("qrc");
#ifdef Q_OS_ANDROID
- local |= file == QStringLiteral("assets");
+ local |= file == QLatin1String("assets");
#endif
return local;
}
@@ -250,9 +250,16 @@ QUrl QFileSelector::select(const QUrl &filePath) const
return filePath;
QUrl ret(filePath);
if (isLocalScheme(filePath.scheme())) {
- QString equivalentPath = QLatin1Char(':') + filePath.path();
+ QLatin1String scheme(":");
+#ifdef Q_OS_ANDROID
+ // use other scheme because ":" means "qrc" here
+ if (filePath.scheme() == QLatin1String("assets"))
+ scheme = QLatin1String("assets:");
+#endif
+
+ QString equivalentPath = scheme + filePath.path();
QString selectedPath = d->select(equivalentPath);
- ret.setPath(selectedPath.remove(0, 1));
+ ret.setPath(selectedPath.remove(0, scheme.size()));
} else {
ret = QUrl::fromLocalFile(d->select(ret.toLocalFile()));
}
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 41feca8a77..7509307839 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -730,29 +730,33 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
qint64 writtenBytes = 0;
- if (fh) {
- // Buffered stdlib mode.
-
- size_t result;
- do {
- result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
- writtenBytes += result;
- } while (result == 0 ? errno == EINTR : writtenBytes < len);
+ if (len) { // avoid passing nullptr to fwrite() or QT_WRITE() (UB)
- } else if (fd != -1) {
- // Unbuffered stdio mode.
+ if (fh) {
+ // Buffered stdlib mode.
+
+ size_t result;
+ do {
+ result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
+ writtenBytes += result;
+ } while (result == 0 ? errno == EINTR : writtenBytes < len);
+
+ } else if (fd != -1) {
+ // Unbuffered stdio mode.
+
+ SignedIOType result;
+ do {
+ // calculate the chunk size
+ // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks
+ // we limit to the size of the signed type, otherwise we could get a negative number as a result
+ quint64 wantedBytes = quint64(len) - quint64(writtenBytes);
+ UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
+ if (chunkSize > wantedBytes)
+ chunkSize = wantedBytes;
+ result = QT_WRITE(fd, data + writtenBytes, chunkSize);
+ } while (result > 0 && (writtenBytes += result) < len);
+ }
- SignedIOType result;
- do {
- // calculate the chunk size
- // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks
- // we limit to the size of the signed type, otherwise we could get a negative number as a result
- quint64 wantedBytes = quint64(len) - quint64(writtenBytes);
- UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
- if (chunkSize > wantedBytes)
- chunkSize = wantedBytes;
- result = QT_WRITE(fd, data + writtenBytes, chunkSize);
- } while (result > 0 && (writtenBytes += result) < len);
}
if (len && writtenBytes == 0) {
diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h
index 7ea79553e4..b41b9b4604 100644
--- a/src/corelib/io/qlockfile_p.h
+++ b/src/corelib/io/qlockfile_p.h
@@ -84,7 +84,7 @@ public:
static QString processNameByPid(qint64 pid);
#ifdef Q_OS_UNIX
- static int checkFcntlWorksAfterFlock();
+ static int checkFcntlWorksAfterFlock(const QString &fn);
#endif
QString fileName;
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index 8bb94ee6c1..14ad103c4e 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -45,6 +45,10 @@
#include "QtCore/qfileinfo.h"
#include "QtCore/qdebug.h"
#include "QtCore/qdatetime.h"
+#include "QtCore/qfileinfo.h"
+#include "QtCore/qcache.h"
+#include "QtCore/qglobalstatic.h"
+#include "QtCore/qmutex.h"
#include "private/qcore_unix_p.h" // qt_safe_open
#include "private/qabstractfileengine_p.h"
@@ -100,10 +104,10 @@ static qint64 qt_write_loop(int fd, const char *data, qint64 len)
return pos;
}
-int QLockFilePrivate::checkFcntlWorksAfterFlock()
+int QLockFilePrivate::checkFcntlWorksAfterFlock(const QString &fn)
{
#ifndef QT_NO_TEMPORARYFILE
- QTemporaryFile file;
+ QTemporaryFile file(fn);
if (!file.open())
return 0;
const int fd = file.d_func()->engine()->handle();
@@ -125,24 +129,34 @@ int QLockFilePrivate::checkFcntlWorksAfterFlock()
#endif
}
-static QBasicAtomicInt fcntlOK = Q_BASIC_ATOMIC_INITIALIZER(-1);
+// Cache the result of checkFcntlWorksAfterFlock for each directory a lock
+// file is created in because in some filesystems, like NFS, both locks
+// are the same. This does not take into account a filesystem changing.
+// QCache is set to hold a maximum of 10 entries, this is to avoid unbounded
+// growth, this is caching directories of files and it is assumed a low number
+// will be sufficient.
+typedef QCache<QString, bool> CacheType;
+Q_GLOBAL_STATIC_WITH_ARGS(CacheType, fcntlOK, (10));
+static QBasicMutex fcntlLock;
/*!
\internal
Checks that the OS isn't using POSIX locks to emulate flock().
OS X is one of those.
*/
-static bool fcntlWorksAfterFlock()
+static bool fcntlWorksAfterFlock(const QString &fn)
{
- int value = fcntlOK.load();
- if (Q_UNLIKELY(value == -1)) {
- value = QLockFilePrivate::checkFcntlWorksAfterFlock();
- fcntlOK.store(value);
+ QMutexLocker lock(&fcntlLock);
+ bool *worksPtr = fcntlOK->object(fn);
+ if (!worksPtr) {
+ worksPtr = new bool(QLockFilePrivate::checkFcntlWorksAfterFlock(fn));
+ fcntlOK->insert(fn, worksPtr);
}
- return value == 1;
+
+ return *worksPtr;
}
-static bool setNativeLocks(int fd)
+static bool setNativeLocks(const QString &fileName, int fd)
{
#if defined(LOCK_EX) && defined(LOCK_NB)
if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs
@@ -154,8 +168,10 @@ static bool setNativeLocks(int fd)
flockData.l_start = 0;
flockData.l_len = 0; // 0 = entire file
flockData.l_pid = getpid();
- if (fcntlWorksAfterFlock() && fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems
+ if (fcntlWorksAfterFlock(QDir::cleanPath(QFileInfo(fileName).absolutePath()) + QString('/'))
+ && fcntl(fd, F_SETLK, &flockData) == -1) { // for networked filesystems
return false;
+ }
return true;
}
@@ -182,7 +198,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
}
}
// Ensure nobody else can delete the file while we have it
- if (!setNativeLocks(fd)) {
+ if (!setNativeLocks(fileName, fd)) {
const int errnoSaved = errno;
qWarning() << "setNativeLocks failed:" << qt_error_string(errnoSaved);
}
@@ -213,7 +229,7 @@ bool QLockFilePrivate::removeStaleLock()
const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644);
if (fd < 0) // gone already?
return false;
- bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0);
+ bool success = setNativeLocks(fileName, fd) && (::unlink(lockFileName) == 0);
close(fd);
return success;
}
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 956207961c..dcbd69c5e5 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1408,13 +1408,17 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
Concurrent read and write are not a problem because the writing operation is atomic.
*/
QLockFile lockFile(confFile->name + QLatin1String(".lock"));
+#endif
if (!readOnly) {
- if (!confFile->isWritable() || !lockFile.lock() ) {
+ if (!confFile->isWritable()
+#ifndef QT_BOOTSTRAPPED
+ || !lockFile.lock()
+#endif
+ ) {
setStatus(QSettings::AccessError);
return;
}
}
-#endif
/*
We hold the lock. Let's reread the file if it has changed
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index e88024661d..ed119f61b6 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -562,6 +562,7 @@ public:
inline bool hasFragment() const { return sectionIsPresent & Fragment; }
inline bool isLocalFile() const { return flags & IsLocalFile; }
+ QString toLocalFile(QUrl::FormattingOptions options) const;
QString mergePaths(const QString &relativePath) const;
@@ -1466,6 +1467,33 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode
validateComponent(Fragment, url, hash + 1, len);
}
+QString QUrlPrivate::toLocalFile(QUrl::FormattingOptions options) const
+{
+ QString tmp;
+ QString ourPath;
+ appendPath(ourPath, options, QUrlPrivate::Path);
+
+ // magic for shared drive on windows
+ if (!host.isEmpty()) {
+ tmp = QStringLiteral("//") + host;
+#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only.
+ if (scheme == webDavScheme())
+ tmp += webDavSslTag();
+#endif
+ if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/')))
+ tmp += QLatin1Char('/');
+ tmp += ourPath;
+ } else {
+ tmp = ourPath;
+#ifdef Q_OS_WIN
+ // magic for drives on windows
+ if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':'))
+ tmp.remove(0, 1);
+#endif
+ }
+ return tmp;
+}
+
/*
From http://www.ietf.org/rfc/rfc3986.txt, 5.2.3: Merge paths
@@ -3263,7 +3291,7 @@ QString QUrl::toString(FormattingOptions options) const
&& (!d->hasQuery() || options.testFlag(QUrl::RemoveQuery))
&& (!d->hasFragment() || options.testFlag(QUrl::RemoveFragment))
&& isLocalFile()) {
- return path(options);
+ return d->toLocalFile(options);
}
QString url;
@@ -3826,28 +3854,7 @@ QString QUrl::toLocalFile() const
if (!isLocalFile())
return QString();
- QString tmp;
- QString ourPath = path(QUrl::FullyDecoded);
-
- // magic for shared drive on windows
- if (!d->host.isEmpty()) {
- tmp = QStringLiteral("//") + host();
-#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only.
- if (scheme() == webDavScheme())
- tmp += webDavSslTag();
-#endif
- if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/')))
- tmp += QLatin1Char('/');
- tmp += ourPath;
- } else {
- tmp = ourPath;
-#ifdef Q_OS_WIN
- // magic for drives on windows
- if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':'))
- tmp.remove(0, 1);
-#endif
- }
- return tmp;
+ return d->toLocalFile(QUrl::FullyDecoded);
}
/*!
diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp
index 7c27a85e3e..3f599e464f 100644
--- a/src/corelib/io/qwinoverlappedionotifier.cpp
+++ b/src/corelib/io/qwinoverlappedionotifier.cpp
@@ -370,7 +370,7 @@ bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped
return false;
if (triggeredOverlapped == overlapped)
return true;
- msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
+ t = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
if (t == 0)
return false;
}