summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2015-06-03 10:23:56 +0200
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2015-06-03 10:23:56 +0200
commite2f66f921594b7be4af4a058c959557489e86879 (patch)
treecc44931708b57bd5a761906797c7dee0360d1d6b /src/corelib/io
parent933bf178aab88ab5df8a68cbf02611d6d8744b1b (diff)
parent754efa57d89c62d1796e01b407e9222e67450f52 (diff)
Merge remote-tracking branch 'origin/5.5' into dev
Conflicts: src/corelib/global/qnamespace.qdoc src/corelib/io/qwindowspipereader.cpp src/corelib/io/qwindowspipereader_p.h src/corelib/statemachine/qstatemachine.cpp src/corelib/statemachine/qstatemachine_p.h src/plugins/platforms/xcb/qxcbconnection.h tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp tests/auto/tools/qmake/tst_qmake.cpp tests/manual/touch/main.cpp Change-Id: I917d694890e79ee3da7d65134b5b085e23e0dd62
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/io.pri2
-rw-r--r--src/corelib/io/qfileselector.cpp12
-rw-r--r--src/corelib/io/qfilesystementry.cpp16
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp4
-rw-r--r--src/corelib/io/qiodevice.cpp53
-rw-r--r--src/corelib/io/qlockfile.cpp12
-rw-r--r--src/corelib/io/qlockfile_p.h1
-rw-r--r--src/corelib/io/qlockfile_unix.cpp58
-rw-r--r--src/corelib/io/qlockfile_win.cpp73
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp18
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h4
-rw-r--r--src/corelib/io/qsettings.cpp6
-rw-r--r--src/corelib/io/qstandardpaths.cpp30
-rw-r--r--src/corelib/io/qstandardpaths_ios.mm29
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp24
-rw-r--r--src/corelib/io/qtextstream.cpp12
-rw-r--r--src/corelib/io/qurl.h4
-rw-r--r--src/corelib/io/qwindowspipereader.cpp102
-rw-r--r--src/corelib/io/qwindowspipereader_p.h4
19 files changed, 321 insertions, 143 deletions
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index 4c189bfe57..207de2a85b 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -187,7 +187,7 @@ win32 {
}
!nacl {
- freebsd-*|mac|darwin-*|openbsd-*:{
+ freebsd-*|mac|darwin-*|openbsd-*|netbsd-*:{
SOURCES += io/qfilesystemwatcher_kqueue.cpp
HEADERS += io/qfilesystemwatcher_kqueue_p.h
}
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index 4ca07ba41d..cddd70f908 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -225,9 +225,13 @@ QString QFileSelector::select(const QString &filePath) const
return d->select(filePath);
}
-static QString qrcScheme()
+static bool isLocalScheme(const QString &file)
{
- return QStringLiteral("qrc");
+ bool local = file == QStringLiteral("qrc");
+#ifdef Q_OS_ANDROID
+ local |= file == QStringLiteral("assets");
+#endif
+ return local;
}
/*!
@@ -240,10 +244,10 @@ static QString qrcScheme()
QUrl QFileSelector::select(const QUrl &filePath) const
{
Q_D(const QFileSelector);
- if (filePath.scheme() != qrcScheme() && !filePath.isLocalFile())
+ if (!isLocalScheme(filePath.scheme()) && !filePath.isLocalFile())
return filePath;
QUrl ret(filePath);
- if (filePath.scheme() == qrcScheme()) {
+ if (isLocalScheme(filePath.scheme())) {
QString equivalentPath = QLatin1Char(':') + filePath.path();
QString selectedPath = d->select(equivalentPath);
ret.setPath(selectedPath.remove(0, 1));
diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp
index faaf7a00af..79f16a0839 100644
--- a/src/corelib/io/qfilesystementry.cpp
+++ b/src/corelib/io/qfilesystementry.cpp
@@ -255,15 +255,15 @@ QString QFileSystemEntry::completeSuffix() const
bool QFileSystemEntry::isRelative() const
{
resolveFilePath();
- return (m_filePath.isEmpty() || (!m_filePath.isEmpty() && (m_filePath[0].unicode() != '/')
- && (!(m_filePath.length() >= 2 && m_filePath[1].unicode() == ':'))));
+ return (m_filePath.isEmpty() || (!m_filePath.isEmpty() && (m_filePath.at(0).unicode() != '/')
+ && (!(m_filePath.length() >= 2 && m_filePath.at(1).unicode() == ':'))));
}
bool QFileSystemEntry::isAbsolute() const
{
resolveFilePath();
return (!m_filePath.isEmpty() && ((m_filePath.length() >= 3
- && (m_filePath[0].isLetter() && m_filePath[1].unicode() == ':' && m_filePath[2].unicode() == '/'))
+ && (m_filePath.at(0).isLetter() && m_filePath.at(1).unicode() == ':' && m_filePath.at(2).unicode() == '/'))
|| (m_filePath.length() >= 2 && (m_filePath.at(0) == QLatin1Char('/') && m_filePath.at(1) == QLatin1Char('/')))
));
}
@@ -276,7 +276,7 @@ bool QFileSystemEntry::isRelative() const
bool QFileSystemEntry::isAbsolute() const
{
resolveFilePath();
- return (!m_filePath.isEmpty() && (m_filePath[0].unicode() == '/'));
+ return (!m_filePath.isEmpty() && (m_filePath.at(0).unicode() == '/'));
}
#endif
@@ -337,10 +337,10 @@ void QFileSystemEntry::findFileNameSeparators() const
int i = m_filePath.size() - 1;
for (; i >= stop; --i) {
- if (m_filePath[i].unicode() == '.') {
+ if (m_filePath.at(i).unicode() == '.') {
firstDotInFileName = lastDotInFileName = i;
break;
- } else if (m_filePath[i].unicode() == '/') {
+ } else if (m_filePath.at(i).unicode() == '/') {
lastSeparator = i;
break;
}
@@ -348,9 +348,9 @@ void QFileSystemEntry::findFileNameSeparators() const
if (lastSeparator != i) {
for (--i; i >= stop; --i) {
- if (m_filePath[i].unicode() == '.')
+ if (m_filePath.at(i).unicode() == '.')
firstDotInFileName = i;
- else if (m_filePath[i].unicode() == '/') {
+ else if (m_filePath.at(i).unicode() == '/') {
lastSeparator = i;
break;
}
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index 0bd46400d3..3a8f7bd0a9 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -52,7 +52,7 @@
# include "qfilesystemwatcher_win_p.h"
#elif defined(USE_INOTIFY)
# include "qfilesystemwatcher_inotify_p.h"
-#elif defined(Q_OS_FREEBSD) || defined(Q_OS_IOS)
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_IOS)
# include "qfilesystemwatcher_kqueue_p.h"
#elif defined(Q_OS_OSX)
# include "qfilesystemwatcher_fsevents_p.h"
@@ -68,7 +68,7 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject
// there is a chance that inotify may fail on Linux pre-2.6.13 (August
// 2005), so we can't just new inotify directly.
return QInotifyFileSystemWatcherEngine::create(parent);
-#elif defined(Q_OS_FREEBSD) || defined(Q_OS_IOS)
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_IOS)
return QKqueueFileSystemWatcherEngine::create(parent);
#elif defined(Q_OS_OSX)
return QFseventsFileSystemWatcherEngine::create(parent);
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index d68f33287d..07a2ff8f6b 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -38,9 +38,9 @@
#include "qiodevice_p.h"
#include "qfile.h"
#include "qstringlist.h"
+#include "qdir.h"
#include <algorithm>
-#include <limits.h>
#ifdef QIODEVICE_DEBUG
# include <ctype.h>
@@ -80,10 +80,29 @@ void debugBinaryString(const char *data, qint64 maxlen)
#define Q_VOID
+static void checkWarnMessage(const QIODevice *device, const char *function, const char *what)
+{
+ QDebug d = qWarning();
+ d.noquote();
+ d.nospace();
+ d << "QIODevice::" << function;
+#ifndef QT_NO_QOBJECT
+ d << " (" << device->metaObject()->className();
+ if (!device->objectName().isEmpty())
+ d << ", \"" << device->objectName() << '"';
+ if (const QFile *f = qobject_cast<const QFile *>(device))
+ d << ", \"" << QDir::toNativeSeparators(f->fileName()) << '"';
+ d << ')';
+#else
+ Q_UNUSED(device)
+#endif // !QT_NO_QOBJECT
+ d << ": " << what;
+}
+
#define CHECK_MAXLEN(function, returnType) \
do { \
if (maxSize < 0) { \
- qWarning("QIODevice::"#function": Called with maxSize < 0"); \
+ checkWarnMessage(this, #function, "Called with maxSize < 0"); \
return returnType; \
} \
} while (0)
@@ -92,10 +111,10 @@ void debugBinaryString(const char *data, qint64 maxlen)
do { \
if ((d->openMode & WriteOnly) == 0) { \
if (d->openMode == NotOpen) { \
- qWarning("QIODevice::"#function": device not open"); \
+ checkWarnMessage(this, #function, "device not open"); \
return returnType; \
} \
- qWarning("QIODevice::"#function": ReadOnly device"); \
+ checkWarnMessage(this, #function, "ReadOnly device"); \
return returnType; \
} \
} while (0)
@@ -104,10 +123,10 @@ void debugBinaryString(const char *data, qint64 maxlen)
do { \
if ((d->openMode & ReadOnly) == 0) { \
if (d->openMode == NotOpen) { \
- qWarning("QIODevice::"#function": device not open"); \
+ checkWarnMessage(this, #function, "device not open"); \
return returnType; \
} \
- qWarning("QIODevice::"#function": WriteOnly device"); \
+ checkWarnMessage(this, #function, "WriteOnly device"); \
return returnType; \
} \
} while (0)
@@ -462,7 +481,7 @@ void QIODevice::setTextModeEnabled(bool enabled)
{
Q_D(QIODevice);
if (!isOpen()) {
- qWarning("QIODevice::setTextModeEnabled: The device is not open");
+ checkWarnMessage(this, "setTextModeEnabled", "The device is not open");
return;
}
if (enabled)
@@ -621,11 +640,11 @@ bool QIODevice::seek(qint64 pos)
{
Q_D(QIODevice);
if (d->isSequential()) {
- qWarning("QIODevice::seek: Cannot call seek on a sequential device");
+ checkWarnMessage(this, "seek", "Cannot call seek on a sequential device");
return false;
}
if (d->openMode == NotOpen) {
- qWarning("QIODevice::seek: The device is not open");
+ checkWarnMessage(this, "seek", "The device is not open");
return false;
}
if (pos < 0) {
@@ -922,9 +941,9 @@ QByteArray QIODevice::read(qint64 maxSize)
Q_UNUSED(d);
#endif
- if (maxSize != qint64(int(maxSize))) {
- qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
- maxSize = INT_MAX;
+ if (quint64(maxSize) >= QByteArray::MaxSize) {
+ checkWarnMessage(this, "read", "maxSize argument exceeds QByteArray size limit");
+ maxSize = QByteArray::MaxSize - 1;
}
qint64 readBytes = 0;
@@ -976,7 +995,7 @@ QByteArray QIODevice::readAll()
// flush internal read buffer
if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
- if (d->buffer.size() >= INT_MAX)
+ if (quint64(d->buffer.size()) >= QByteArray::MaxSize)
return QByteArray();
result = d->buffer.readAll();
readBytes = result.size();
@@ -1055,7 +1074,7 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
{
Q_D(QIODevice);
if (maxSize < 2) {
- qWarning("QIODevice::readLine: Called with maxSize < 2");
+ checkWarnMessage(this, "readLine", "Called with maxSize < 2");
return qint64(-1);
}
@@ -1159,9 +1178,9 @@ QByteArray QIODevice::readLine(qint64 maxSize)
Q_UNUSED(d);
#endif
- if (maxSize > INT_MAX) {
+ if (quint64(maxSize) >= QByteArray::MaxSize) {
qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
- maxSize = INT_MAX;
+ maxSize = QByteArray::MaxSize - 1;
}
result.resize(int(maxSize));
@@ -1169,7 +1188,7 @@ QByteArray QIODevice::readLine(qint64 maxSize)
if (!result.size()) {
// If resize fails or maxSize == 0, read incrementally
if (maxSize == 0)
- maxSize = INT_MAX;
+ maxSize = QByteArray::MaxSize - 1;
// The first iteration needs to leave an extra byte for the terminating null
result.resize(1);
diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp
index 4f5aeff395..2bd996d213 100644
--- a/src/corelib/io/qlockfile.cpp
+++ b/src/corelib/io/qlockfile.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -66,9 +67,12 @@ QT_BEGIN_NAMESPACE
If the process holding the lock crashes, the lock file stays on disk and can prevent
any other process from accessing the shared resource, ever. For this reason, QLockFile
- tries to detect such a "stale" lock file, based on the process ID written into the file,
- and (in case that process ID got reused meanwhile), on the last modification time of
- the lock file (30s by default, for the use case of a short-lived operation).
+ tries to detect such a "stale" lock file, based on the process ID written into the file.
+ To cover the situation that the process ID got reused meanwhile, the current process name is
+ compared to the name of the process that corresponds to the process ID from the lock file.
+ If the process names differ, the lock file is considered stale.
+ Additionally, the last modification time of the lock file (30s by default, for the use case of a
+ short-lived operation) is taken into account.
If the lock file is found to be stale, it will be deleted.
For the use case of protecting a resource over a long time, you should therefore call
@@ -122,7 +126,7 @@ QLockFile::~QLockFile()
The value of \a staleLockTime is used by lock() and tryLock() in order
to determine when an existing lock file is considered stale, i.e. left over
by a crashed process. This is useful for the case where the PID got reused
- meanwhile, so the only way to detect a stale lock file is by the fact that
+ meanwhile, so one way to detect a stale lock file is by the fact that
it has been around for a long time.
\sa staleLockTime()
diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h
index 0cfaa42849..168062f467 100644
--- a/src/corelib/io/qlockfile_p.h
+++ b/src/corelib/io/qlockfile_p.h
@@ -75,6 +75,7 @@ public:
// Returns \c true if the lock belongs to dead PID, or is old.
// The attempt to delete it will tell us if it was really stale or not, though.
bool isApparentlyStale() const;
+ static QString processNameByPid(qint64 pid);
#ifdef Q_OS_UNIX
static int checkFcntlWorksAfterFlock();
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index b817a24c74..d6ea2f1f2d 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -48,6 +49,15 @@
#include <signal.h> // kill
#include <unistd.h> // gethostname
+#if defined(Q_OS_OSX)
+# include <libproc.h>
+#elif defined(Q_OS_LINUX)
+# include <unistd.h>
+# include <cstdio>
+#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
+# include <sys/user.h>
+#endif
+
QT_BEGIN_NAMESPACE
static QByteArray localHostName() // from QHostInfo::localHostName(), modified to return a QByteArray
@@ -185,16 +195,54 @@ bool QLockFilePrivate::isApparentlyStale() const
{
qint64 pid;
QString hostname, appname;
- if (!getLockInfo(&pid, &hostname, &appname))
- return false;
- if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
- if (::kill(pid, 0) == -1 && errno == ESRCH)
- return true; // PID doesn't exist anymore
+ if (getLockInfo(&pid, &hostname, &appname)) {
+ if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
+ if (::kill(pid, 0) == -1 && errno == ESRCH)
+ return true; // PID doesn't exist anymore
+ const QString processName = processNameByPid(pid);
+ if (!processName.isEmpty()) {
+ QFileInfo fi(appname);
+ if (fi.isSymLink())
+ fi.setFile(fi.symLinkTarget());
+ if (processName != fi.fileName())
+ return true; // PID got reused by a different application.
+ }
+ }
}
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
return staleLockTime > 0 && age > staleLockTime;
}
+QString QLockFilePrivate::processNameByPid(qint64 pid)
+{
+#if defined(Q_OS_OSX)
+ char name[1024];
+ proc_name(pid, name, sizeof(name) / sizeof(char));
+ return QString::fromUtf8(name);
+#elif defined(Q_OS_LINUX)
+ if (!QFile::exists(QStringLiteral("/proc/version")))
+ return QString();
+ char exePath[64];
+ char buf[PATH_MAX];
+ memset(buf, 0, sizeof(buf));
+ sprintf(exePath, "/proc/%lld/exe", pid);
+ if (readlink(exePath, buf, sizeof(buf)) < 0) {
+ // The pid is gone. Return some invalid process name to fail the test.
+ return QStringLiteral("/ERROR/");
+ }
+ return QFileInfo(QString::fromUtf8(buf)).fileName();
+#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
+ kinfo_proc *proc = kinfo_getproc(pid);
+ if (!proc)
+ return QString();
+ QString name = QString::fromUtf8(proc->ki_comm);
+ free(proc);
+ return name;
+#else
+ return QString();
+#endif
+}
+
void QLockFile::unlock()
{
Q_D(QLockFile);
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
index 9fe86e1ad8..5bd1ba04c9 100644
--- a/src/corelib/io/qlockfile_win.cpp
+++ b/src/corelib/io/qlockfile_win.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -126,27 +127,75 @@ bool QLockFilePrivate::isApparentlyStale() const
{
qint64 pid;
QString hostname, appname;
- if (!getLockInfo(&pid, &hostname, &appname))
- return false;
// On WinRT there seems to be no way of obtaining information about other
// processes due to sandboxing
#ifndef Q_OS_WINRT
- if (hostname == QString::fromLocal8Bit(localHostName())) {
- HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
- if (!procHandle)
- return true;
- // We got a handle but check if process is still alive
- DWORD dwR = ::WaitForSingleObject(procHandle, 0);
- ::CloseHandle(procHandle);
- if (dwR == WAIT_TIMEOUT)
- return true;
+ if (getLockInfo(&pid, &hostname, &appname)) {
+ if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
+ HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
+ if (!procHandle)
+ return true;
+ // We got a handle but check if process is still alive
+ DWORD dwR = ::WaitForSingleObject(procHandle, 0);
+ ::CloseHandle(procHandle);
+ if (dwR == WAIT_TIMEOUT)
+ return true;
+ const QString processName = processNameByPid(pid);
+ if (!processName.isEmpty() && processName != appname)
+ return true; // PID got reused by a different application.
+ }
}
-#endif // !Q_OS_WINRT
+#else // !Q_OS_WINRT
+ Q_UNUSED(pid);
+ Q_UNUSED(hostname);
+ Q_UNUSED(appname);
+#endif // Q_OS_WINRT
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
return staleLockTime > 0 && age > staleLockTime;
}
+QString QLockFilePrivate::processNameByPid(qint64 pid)
+{
+#if !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
+ typedef DWORD (WINAPI *GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD);
+
+ HMODULE hPsapi = LoadLibraryA("psapi");
+ if (!hPsapi)
+ return QString();
+
+ GetModuleFileNameExFunc qGetModuleFileNameEx
+ = (GetModuleFileNameExFunc)GetProcAddress(hPsapi, "GetModuleFileNameExW");
+ if (!qGetModuleFileNameEx) {
+ FreeLibrary(hPsapi);
+ return QString();
+ }
+
+ HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid));
+ if (!hProcess) {
+ FreeLibrary(hPsapi);
+ return QString();
+ }
+ wchar_t buf[MAX_PATH];
+ const DWORD length = qGetModuleFileNameEx(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t));
+ CloseHandle(hProcess);
+ FreeLibrary(hPsapi);
+ if (!length)
+ return QString();
+ QString name = QString::fromWCharArray(buf, length);
+ int i = name.lastIndexOf(QLatin1Char('\\'));
+ if (i >= 0)
+ name.remove(0, i + 1);
+ i = name.lastIndexOf(QLatin1Char('.'));
+ if (i >= 0)
+ name.truncate(i);
+ return name;
+#else
+ Q_UNUSED(pid);
+ return QString();
+#endif
+}
+
void QLockFile::unlock()
{
Q_D(QLockFile);
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index c17b42ef81..af1bb56fe9 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -216,6 +216,11 @@ qint64 QNonContiguousByteDeviceByteArrayImpl::size()
return byteArray->size();
}
+qint64 QNonContiguousByteDeviceByteArrayImpl::pos()
+{
+ return currentPosition;
+}
+
QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QSharedPointer<QRingBuffer> rb)
: QNonContiguousByteDevice(), currentPosition(0)
{
@@ -253,6 +258,11 @@ bool QNonContiguousByteDeviceRingBufferImpl::atEnd()
return currentPosition >= size();
}
+qint64 QNonContiguousByteDeviceRingBufferImpl::pos()
+{
+ return currentPosition;
+}
+
bool QNonContiguousByteDeviceRingBufferImpl::reset()
{
currentPosition = 0;
@@ -381,6 +391,14 @@ qint64 QNonContiguousByteDeviceIoDeviceImpl::size()
return device->size() - initialPosition;
}
+qint64 QNonContiguousByteDeviceIoDeviceImpl::pos()
+{
+ if (device->isSequential())
+ return -1;
+
+ return device->pos();
+}
+
QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0)
{
byteDevice = bd;
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index 8b5bf3080a..38089dedd7 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -61,6 +61,7 @@ public:
virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
virtual bool advanceReadPointer(qint64 amount) = 0;
virtual bool atEnd() = 0;
+ virtual qint64 pos() { return -1; }
virtual bool reset() = 0;
virtual qint64 size() = 0;
@@ -103,6 +104,7 @@ public:
bool atEnd() Q_DECL_OVERRIDE;
bool reset() Q_DECL_OVERRIDE;
qint64 size() Q_DECL_OVERRIDE;
+ qint64 pos() Q_DECL_OVERRIDE;
protected:
QByteArray* byteArray;
qint64 currentPosition;
@@ -118,6 +120,7 @@ public:
bool atEnd() Q_DECL_OVERRIDE;
bool reset() Q_DECL_OVERRIDE;
qint64 size() Q_DECL_OVERRIDE;
+ qint64 pos() Q_DECL_OVERRIDE;
protected:
QSharedPointer<QRingBuffer> ringBuffer;
qint64 currentPosition;
@@ -135,6 +138,7 @@ public:
bool atEnd() Q_DECL_OVERRIDE;
bool reset() Q_DECL_OVERRIDE;
qint64 size() Q_DECL_OVERRIDE;
+ qint64 pos() Q_DECL_OVERRIDE;
protected:
QIODevice* device;
QByteArray* currentReadBuffer;
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index cb6de29532..251b10ea89 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -104,6 +104,10 @@ using namespace ABI::Windows::Storage;
#define Q_XDG_PLATFORM
#endif
+#if !defined(QT_NO_STANDARDPATHS) && (defined(Q_XDG_PLATFORM) || defined(Q_OS_IOS))
+#define QSETTINGS_USE_QSTANDARDPATHS
+#endif
+
// ************************************************************************
// QConfFile
@@ -1044,7 +1048,7 @@ static void initDefaultPaths(QMutexLocker *locker)
windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator());
#else
-#if defined(QT_NO_STANDARDPATHS) || !defined(Q_XDG_PLATFORM)
+#ifndef QSETTINGS_USE_QSTANDARDPATHS
// Non XDG platforms (OS X, iOS, Blackberry, Android...) have used this code path erroneously
// for some time now. Moving away from that would require migrating existing settings.
QString userPath;
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index beb5d29d54..04848a38e5 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -274,45 +274,67 @@ QT_BEGIN_NAMESPACE
\endtable
\table
- \header \li Path type \li Android
+ \header \li Path type \li Android \li iOS
\row \li DesktopLocation
\li "<APPROOT>/files"
+ \li "<APPROOT>/<APPDIR>" (not writable)
\row \li DocumentsLocation
\li "<USER>/Documents", "<USER>/<APPNAME>/Documents"
+ \li "<APPROOT>/Documents"
\row \li FontsLocation
\li "/system/fonts" (not writable)
+ \li "<APPROOT>/Documents/.fonts"
\row \li ApplicationsLocation
\li not supported (directory not readable)
+ \li not supported
\row \li MusicLocation
\li "<USER>/Music", "<USER>/<APPNAME>/Music"
+ \li "<APPROOT>/Documents/Music"
\row \li MoviesLocation
\li "<USER>/Movies", "<USER>/<APPNAME>/Movies"
+ \li "<APPROOT>/Documents/Movies"
\row \li PicturesLocation
\li "<USER>/Pictures", "<USER>/<APPNAME>/Pictures"
+ \li "<APPROOT>/Documents/Pictures", "assets-library://"
\row \li TempLocation
\li "<APPROOT>/cache"
+ \li "<APPROOT>/tmp"
\row \li HomeLocation
\li "<APPROOT>/files"
+ \li "<APPROOT>/<APPDIR>" (not writable)
\row \li DataLocation
\li "<APPROOT>/files", "<USER>/<APPNAME>/files"
+ \li "<APPROOT>/Library/Application Support"
\row \li CacheLocation
\li "<APPROOT>/cache", "<USER>/<APPNAME>/cache"
+ \li "<APPROOT>/Library/Caches"
\row \li GenericDataLocation
\li "<USER>"
+ \li "<APPROOT>/Documents"
\row \li RuntimeLocation
\li "<APPROOT>/cache"
+ \li not supported
\row \li ConfigLocation
\li "<APPROOT>/files/settings"
+ \li "<APPROOT>/Documents"
\row \li GenericConfigLocation
\li "<APPROOT>/files/settings" (there is no shared settings)
+ \li "<APPROOT>/Documents"
\row \li DownloadLocation
\li "<USER>/Downloads", "<USER>/<APPNAME>/Downloads"
+ \li "<APPROOT>/Documents/Download"
\row \li GenericCacheLocation
\li "<APPROOT>/cache" (there is no shared cache)
+ \li "<APPROOT>/Library/Caches"
\row \li AppDataLocation
\li "<APPROOT>/files", "<USER>/<APPNAME>/files"
+ \li "<APPROOT>/Library/Application Support"
\row \li AppConfigLocation
\li "<APPROOT>/files/settings"
+ \li "<APPROOT>/Documents"
+ \row \li AppLocalDataLocation
+ \li "<APPROOT>/files", "<USER>/<APPNAME>/files"
+ \li "<APPROOT>/Library/Application Support"
\endtable
In the table above, \c <APPNAME> is usually the organization name, the
@@ -327,6 +349,12 @@ QT_BEGIN_NAMESPACE
\note On Android, applications with open files on the external storage (<USER> locations),
will be killed if the external storage is unmounted.
+ \note On iOS, if you do pass \c {QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last()}
+ as argument to \l{QFileDialog::setDirectory()},
+ a native image picker dialog will be used for accessing the user's photo album.
+ The filename returned can be loaded using QFile and related APIs.
+ This feature was added in Qt 5.5.
+
\sa writableLocation(), standardLocations(), displayName(), locate(), locateAll()
*/
diff --git a/src/corelib/io/qstandardpaths_ios.mm b/src/corelib/io/qstandardpaths_ios.mm
index 27d28526c2..eb85e2fd23 100644
--- a/src/corelib/io/qstandardpaths_ios.mm
+++ b/src/corelib/io/qstandardpaths_ios.mm
@@ -55,30 +55,31 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QString location;
switch (type) {
- case DesktopLocation:
- location = pathForDirectory(NSDesktopDirectory);
- break;
case DocumentsLocation:
location = pathForDirectory(NSDocumentDirectory);
break;
case FontsLocation:
- location = bundlePath() + QLatin1String("/.fonts");
+ location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/.fonts");
break;
case ApplicationsLocation:
- location = pathForDirectory(NSApplicationDirectory);
+ // NSApplicationDirectory points to a non-existing write-protected path.
break;
case MusicLocation:
- location = pathForDirectory(NSMusicDirectory);
+ // NSMusicDirectory points to a non-existing write-protected path. Use sensible fallback.
+ location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Music");
break;
case MoviesLocation:
- location = pathForDirectory(NSMoviesDirectory);
+ // NSMoviesDirectory points to a non-existing write-protected path. Use sensible fallback.
+ location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Movies");
break;
case PicturesLocation:
- location = pathForDirectory(NSPicturesDirectory);
+ // NSPicturesDirectory points to a non-existing write-protected path. Use sensible fallback.
+ location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Pictures");
break;
case TempLocation:
location = QString::fromNSString(NSTemporaryDirectory());
break;
+ case DesktopLocation:
case HomeLocation:
location = bundlePath();
break;
@@ -99,20 +100,12 @@ QString QStandardPaths::writableLocation(StandardLocation type)
location = pathForDirectory(NSDocumentDirectory);
break;
case DownloadLocation:
- location = pathForDirectory(NSDownloadsDirectory);
- break;
- default:
+ // NSDownloadsDirectory points to a non-existing write-protected path.
+ location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Download");
break;
- }
-
- switch (type) {
case RuntimeLocation:
break;
default:
- // All other types must return something, so use the document directory
- // as a reasonable fall-back (which will always exist).
- if (location.isEmpty())
- location = pathForDirectory(NSDocumentDirectory);
break;
}
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index 7823787711..f82d0ff0a1 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -67,8 +67,20 @@
#endif
#if defined(Q_OS_BSD4)
-# define QT_STATFSBUF struct statvfs
-# define QT_STATFS ::statvfs
+# if defined(Q_OS_NETBSD)
+ define QT_STATFSBUF struct statvfs
+ define QT_STATFS ::statvfs
+# else
+# define QT_STATFSBUF struct statfs
+# define QT_STATFS ::statfs
+# endif
+
+# if !defined(ST_RDONLY)
+# define ST_RDONLY MNT_RDONLY
+# endif
+# if !defined(_STATFS_F_FLAGS)
+# define _STATFS_F_FLAGS 1
+# endif
#elif defined(Q_OS_ANDROID)
# define QT_STATFS ::statfs
# define QT_STATFSBUF struct statfs
@@ -122,11 +134,7 @@ public:
inline QByteArray device() const;
private:
#if defined(Q_OS_BSD4)
-# if defined(Q_OS_NETBSD)
- struct statvfs *stat_buf;
-# else
- struct statfs *stat_buf;
-# endif
+ QT_STATFSBUF *stat_buf;
int entryCount;
int currentIndex;
#elif defined(Q_OS_SOLARIS)
@@ -502,7 +510,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
-#if defined(Q_OS_ANDROID)
+#if defined(Q_OS_ANDROID) || defined (Q_OS_BSD4)
#if defined(_STATFS_F_FLAGS)
readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
#endif
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 5fe4cfef9d..47b96d708f 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -464,7 +464,7 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
}
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::fillReadBuffer(), using %s codec",
- codec->name().constData());
+ codec ? codec->name().constData() : "no");
#endif
#endif
@@ -476,9 +476,10 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
int oldReadBufferSize = readBuffer.size();
#ifndef QT_NO_TEXTCODEC
// convert to unicode
- readBuffer += codec->toUnicode(buf, bytesRead, &readConverterState);
+ readBuffer += Q_LIKELY(codec) ? codec->toUnicode(buf, bytesRead, &readConverterState)
+ : QString::fromLatin1(buf, bytesRead);
#else
- readBuffer += QString::fromLatin1(QByteArray(buf, bytesRead).constData());
+ readBuffer += QString::fromLatin1(buf, bytesRead);
#endif
// reset the Text flag.
@@ -564,7 +565,8 @@ void QTextStreamPrivate::flushWriteBuffer()
codec = QTextCodec::codecForLocale();
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::flushWriteBuffer(), using %s codec (%s generating BOM)",
- codec->name().constData(), writeConverterState.flags & QTextCodec::IgnoreHeader ? "not" : "");
+ codec ? codec->name().constData() : "no",
+ !codec || (writeConverterState.flags & QTextCodec::IgnoreHeader) ? "not" : "");
#endif
// convert from unicode to raw data
@@ -572,7 +574,7 @@ void QTextStreamPrivate::flushWriteBuffer()
QByteArray data = Q_LIKELY(codec) ? codec->fromUnicode(writeBuffer.data(), writeBuffer.size(), &writeConverterState)
: writeBuffer.toLatin1();
#else
- QByteArray data = writeBuffer.toLocal8Bit();
+ QByteArray data = writeBuffer.toLatin1();
#endif
writeBuffer.clear();
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 945b7df930..e6c570d1db 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -186,7 +186,7 @@ public:
QString url(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
QString toString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
QString toDisplayString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
- QUrl adjusted(FormattingOptions options) const;
+ QUrl adjusted(FormattingOptions options) const Q_REQUIRED_RESULT;
QByteArray toEncoded(FormattingOptions options = FullyEncoded) const;
static QUrl fromEncoded(const QByteArray &url, ParsingMode mode = TolerantMode);
@@ -243,7 +243,7 @@ public:
QString fragment(ComponentFormattingOptions options = PrettyDecoded) const;
void setFragment(const QString &fragment, ParsingMode mode = TolerantMode);
- QUrl resolved(const QUrl &relative) const;
+ QUrl resolved(const QUrl &relative) const Q_REQUIRED_RESULT;
bool isRelative() const;
bool isParentOf(const QUrl &url) const;
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 1502e5dada..2cc5741250 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -36,7 +36,6 @@
#include <qdebug.h>
#include <qelapsedtimer.h>
#include <qeventloop.h>
-#include <qtimer.h>
QT_BEGIN_NAMESPACE
@@ -45,13 +44,11 @@ QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
handle(INVALID_HANDLE_VALUE),
readBufferMaxSize(0),
actualReadBufferSize(0),
- emitReadyReadTimer(new QTimer(this)),
+ stopped(true),
readSequenceStarted(false),
pipeBroken(false),
readyReadEmitted(false)
{
- emitReadyReadTimer->setSingleShot(true);
- connect(emitReadyReadTimer, SIGNAL(timeout()), SIGNAL(readyRead()));
dataReadNotifier = new QWinOverlappedIoNotifier(this);
connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified);
}
@@ -73,12 +70,7 @@ static bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped)
QWindowsPipeReader::~QWindowsPipeReader()
{
- if (readSequenceStarted) {
- if (qt_cancelIo(handle, &overlapped))
- dataReadNotifier->waitForNotified(-1, &overlapped);
- else
- qErrnoWarning("QWindowsPipeReader: qt_cancelIo on handle %x failed.", handle);
- }
+ stop();
}
/*!
@@ -89,9 +81,9 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
readBuffer.clear();
actualReadBufferSize = 0;
handle = hPipeReadEnd;
- ZeroMemory(&overlapped, sizeof(overlapped));
pipeBroken = false;
readyReadEmitted = false;
+ stopped = false;
if (hPipeReadEnd != INVALID_HANDLE_VALUE) {
dataReadNotifier->setHandle(hPipeReadEnd);
dataReadNotifier->setEnabled(true);
@@ -100,13 +92,24 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
/*!
Stops the asynchronous read sequence.
- This function assumes that the file already has been closed.
- It does not cancel any I/O operation.
+ If the read sequence is running then the I/O operation is canceled.
*/
void QWindowsPipeReader::stop()
{
- dataReadNotifier->setEnabled(false);
+ stopped = true;
+ if (readSequenceStarted) {
+ if (qt_cancelIo(handle, &overlapped)) {
+ dataReadNotifier->waitForNotified(-1, &overlapped);
+ } else {
+ const DWORD dwError = GetLastError();
+ if (dwError != ERROR_NOT_FOUND) {
+ qErrnoWarning(dwError, "QWindowsPipeReader: qt_cancelIo on handle %x failed.",
+ handle);
+ }
+ }
+ }
readSequenceStarted = false;
+ dataReadNotifier->setEnabled(false);
handle = INVALID_HANDLE_VALUE;
}
@@ -119,7 +122,7 @@ qint64 QWindowsPipeReader::bytesAvailable() const
}
/*!
- Stops the asynchronous read sequence.
+ Copies at most \c{maxlen} bytes from the internal read buffer to \c{data}.
*/
qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
{
@@ -147,9 +150,7 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
}
if (!pipeBroken) {
- if (!actualReadBufferSize)
- emitReadyReadTimer->stop();
- if (!readSequenceStarted)
+ if (!readSequenceStarted && !stopped)
startAsyncRead();
if (readSoFar == 0)
return -2; // signal EWOULDBLOCK
@@ -172,13 +173,41 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
{
if (&overlapped != notifiedOverlapped)
return;
- if (!completeAsyncRead(numberOfBytesRead, errorCode)) {
+
+ switch (errorCode) {
+ case ERROR_SUCCESS:
+ break;
+ case ERROR_MORE_DATA:
+ // This is not an error. We're connected to a message mode
+ // pipe and the message didn't fit into the pipe's system
+ // buffer. We will read the remaining data in the next call.
+ break;
+ case ERROR_BROKEN_PIPE:
+ case ERROR_PIPE_NOT_CONNECTED:
pipeBroken = true;
+ break;
+ default:
+ emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead"));
+ pipeBroken = true;
+ break;
+ }
+
+ readSequenceStarted = false;
+
+ // After the reader was stopped, the only reason why this function can be called is the
+ // completion of a cancellation. No signals should be emitted, and no new read sequence should
+ // be started in this case.
+ if (stopped)
+ return;
+
+ if (pipeBroken) {
emit pipeClosed();
return;
}
+
+ actualReadBufferSize += numberOfBytesRead;
+ readBuffer.truncate(actualReadBufferSize);
startAsyncRead();
- emitReadyReadTimer->stop();
readyReadEmitted = true;
emit readyRead();
}
@@ -206,6 +235,7 @@ void QWindowsPipeReader::startAsyncRead()
char *ptr = readBuffer.reserve(bytesToRead);
readSequenceStarted = true;
+ ZeroMemory(&overlapped, sizeof(overlapped));
if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
// We get notified by the QWinOverlappedIoNotifier - even in the synchronous case.
return;
@@ -241,38 +271,6 @@ void QWindowsPipeReader::startAsyncRead()
/*!
\internal
- Sets the correct size of the read buffer after a read operation.
- Returns \c false, if an error occurred or the connection dropped.
- */
-bool QWindowsPipeReader::completeAsyncRead(DWORD bytesRead, DWORD errorCode)
-{
- readSequenceStarted = false;
-
- switch (errorCode) {
- case ERROR_SUCCESS:
- break;
- case ERROR_MORE_DATA:
- // This is not an error. We're connected to a message mode
- // pipe and the message didn't fit into the pipe's system
- // buffer. We will read the remaining data in the next call.
- break;
- case ERROR_BROKEN_PIPE:
- case ERROR_PIPE_NOT_CONNECTED:
- return false;
- default:
- emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead"));
- return false;
- }
-
- actualReadBufferSize += bytesRead;
- readBuffer.truncate(actualReadBufferSize);
- if (!emitReadyReadTimer->isActive())
- emitReadyReadTimer->start();
- return true;
-}
-
-/*!
- \internal
Returns the number of available bytes in the pipe.
Sets QWindowsPipeReader::pipeBroken to true if the connection is broken.
*/
diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h
index 53872e2552..c8a66d9511 100644
--- a/src/corelib/io/qwindowspipereader_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -47,7 +47,6 @@
#include <qbytearray.h>
#include <qobject.h>
-#include <qtimer.h>
#include <private/qringbuffer_p.h>
#include <qt_windows.h>
@@ -89,7 +88,6 @@ private Q_SLOTS:
void notified(quint32 numberOfBytesRead, quint32 errorCode, OVERLAPPED *notifiedOverlapped);
private:
- bool completeAsyncRead(DWORD bytesRead, DWORD errorCode);
DWORD checkPipeState();
private:
@@ -99,7 +97,7 @@ private:
qint64 readBufferMaxSize;
QRingBuffer readBuffer;
qint64 actualReadBufferSize;
- QTimer *emitReadyReadTimer;
+ bool stopped;
bool readSequenceStarted;
bool pipeBroken;
bool readyReadEmitted;