diff options
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qfiledevice.cpp | 2 | ||||
-rw-r--r-- | src/corelib/io/qfileselector.cpp | 15 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine.cpp | 46 | ||||
-rw-r--r-- | src/corelib/io/qlockfile_p.h | 2 | ||||
-rw-r--r-- | src/corelib/io/qlockfile_unix.cpp | 42 | ||||
-rw-r--r-- | src/corelib/io/qsettings.cpp | 8 | ||||
-rw-r--r-- | src/corelib/io/qurl.cpp | 53 | ||||
-rw-r--r-- | src/corelib/io/qwinoverlappedionotifier.cpp | 2 |
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; } |