From 5b24d3dd3559826dfa3cac38be525a052003e2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Thu, 13 Jul 2017 08:50:18 +0200 Subject: Add missing constexpr specifier to two iterators The classes themselves and their equality operators are used in constexpr functions/ctors (in QKeyValueIterator) so Visual Studio 2017 expects them to be marked constexpr as well. Currently this causes a compilation error when instantiating a QKeyValueIterator using either of these iterators. Change-Id: I2e3eeaf3b3f11f381a63875e6575dfd82fe56fcb Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/tools/qhash.h | 6 +++--- src/corelib/tools/qmap.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index b2c3cf574d..035ec57957 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -373,7 +373,7 @@ public: typedef const T *pointer; typedef const T &reference; - inline const_iterator() : i(Q_NULLPTR) { } + Q_DECL_CONSTEXPR inline const_iterator() : i(Q_NULLPTR) { } explicit inline const_iterator(void *node) : i(reinterpret_cast(node)) { } #ifdef QT_STRICT_ITERATORS @@ -387,8 +387,8 @@ public: inline const T &value() const { return concrete(i)->value; } inline const T &operator*() const { return concrete(i)->value; } inline const T *operator->() const { return &concrete(i)->value; } - inline bool operator==(const const_iterator &o) const { return i == o.i; } - inline bool operator!=(const const_iterator &o) const { return i != o.i; } + Q_DECL_CONSTEXPR inline bool operator==(const const_iterator &o) const { return i == o.i; } + Q_DECL_CONSTEXPR inline bool operator!=(const const_iterator &o) const { return i != o.i; } inline const_iterator &operator++() { i = QHashData::nextNode(i); diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index a3b11eddcf..37ed24000d 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -473,7 +473,7 @@ public: typedef const T *pointer; typedef const T &reference; - inline const_iterator() : i(Q_NULLPTR) { } + Q_DECL_CONSTEXPR inline const_iterator() : i(Q_NULLPTR) { } inline const_iterator(const Node *node) : i(node) { } #ifdef QT_STRICT_ITERATORS explicit inline const_iterator(const iterator &o) @@ -486,8 +486,8 @@ public: inline const T &value() const { return i->value; } inline const T &operator*() const { return i->value; } inline const T *operator->() const { return &i->value; } - inline bool operator==(const const_iterator &o) const { return i == o.i; } - inline bool operator!=(const const_iterator &o) const { return i != o.i; } + Q_DECL_CONSTEXPR inline bool operator==(const const_iterator &o) const { return i == o.i; } + Q_DECL_CONSTEXPR inline bool operator!=(const const_iterator &o) const { return i != o.i; } inline const_iterator &operator++() { i = i->nextNode(); -- cgit v1.2.3 From 0b6bf289fdffd731af13ad80f1008001a1423dbd Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Sat, 15 Jul 2017 03:30:53 -0700 Subject: Update OS version constants in qsystemdetection.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I8c8fa8861280948bf8488c4465a359858bb625e0 Reviewed-by: Tor Arne Vestbø Reviewed-by: Thiago Macieira --- src/corelib/global/qsystemdetection.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index 3133b4a719..4a2c3f79bb 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -267,6 +267,9 @@ # if !defined(__MAC_10_12) # define __MAC_10_12 101200 # endif +# if !defined(__MAC_10_13) +# define __MAC_10_13 101300 +# endif # if !defined(MAC_OS_X_VERSION_10_7) # define MAC_OS_X_VERSION_10_7 1070 # endif @@ -285,6 +288,9 @@ # if !defined(MAC_OS_X_VERSION_10_12) # define MAC_OS_X_VERSION_10_12 101200 # endif +# if !defined(MAC_OS_X_VERSION_10_13) +# define MAC_OS_X_VERSION_10_13 101300 +# endif # # if !defined(__IPHONE_4_3) # define __IPHONE_4_3 40300 @@ -337,6 +343,18 @@ # if !defined(__IPHONE_10_0) # define __IPHONE_10_0 100000 # endif +# if !defined(__IPHONE_10_1) +# define __IPHONE_10_1 100100 +# endif +# if !defined(__IPHONE_10_2) +# define __IPHONE_10_2 100200 +# endif +# if !defined(__IPHONE_10_3) +# define __IPHONE_10_3 100300 +# endif +# if !defined(__IPHONE_11_0) +# define __IPHONE_11_0 110000 +# endif #endif #ifdef __LSB_VERSION__ -- cgit v1.2.3 From 2d54aac427d588be73a28e52fc59d0e62f975941 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 10 Jul 2017 15:41:37 +0200 Subject: Fix warning messages in QWindowsPipeReader/Writer We forgot to update the warnings when removing qt_cancelIo. Also, use %p instead of %x, because HANDLE is void*. This amends commit fade2958. Change-Id: Ia11d7d094aa6beb939e0be4bbe4ab3654eaa1c02 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwindowspipereader.cpp | 2 +- src/corelib/io/qwindowspipewriter.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index 827ed43b63..4065b19446 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -98,7 +98,7 @@ void QWindowsPipeReader::stop() if (!CancelIoEx(handle, &overlapped)) { const DWORD dwError = GetLastError(); if (dwError != ERROR_NOT_FOUND) { - qErrnoWarning(dwError, "QWindowsPipeReader: qt_cancelIo on handle %x failed.", + qErrnoWarning(dwError, "QWindowsPipeReader: CancelIoEx on handle %p failed.", handle); } } diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 3ab2c70c75..d6ee4741e3 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -211,7 +211,7 @@ void QWindowsPipeWriter::stop() if (!CancelIoEx(handle, &overlapped)) { const DWORD dwError = GetLastError(); if (dwError != ERROR_NOT_FOUND) { - qErrnoWarning(dwError, "QWindowsPipeWriter: qt_cancelIo on handle %x failed.", + qErrnoWarning(dwError, "QWindowsPipeWriter: CancelIoEx on handle %p failed.", handle); } } -- cgit v1.2.3 From c7ec07d40115bef849574c81d619b629af9434a9 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 12 Jul 2017 14:20:54 +0200 Subject: Do not wait in QWindowsPipe{Reader|Writer}::stop() A deadlock can occur if the user does QLocalSocket *ls = new QLocalSocket; ls->moveToThread(t); ... delete ls; Then QLocalSocket calls QWindowsPipeReader::stop() in a different thread than the I/O operation is running in. The waitForNotified(-1) call would then wait indefinitely until the I/O thread is in alertable wait state again. Especially on application shut down this might never be the case, and the application would deadlock. Solve this by detaching the Overlapped object from the QWindowsPipe{Reader|Writer} in stop() and delete it in the callback. Task-number: QTBUG-61643 Change-Id: Ie262d75c5fd92ac7cf7dfcdbf1519050be9fd3c4 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwindowspipereader.cpp | 20 ++++++++++++++------ src/corelib/io/qwindowspipereader_p.h | 2 +- src/corelib/io/qwindowspipewriter.cpp | 20 ++++++++++++++------ src/corelib/io/qwindowspipewriter_p.h | 2 +- 4 files changed, 30 insertions(+), 14 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index 4065b19446..b93fed5ba8 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -57,7 +57,7 @@ void QWindowsPipeReader::Overlapped::clear() QWindowsPipeReader::QWindowsPipeReader(QObject *parent) : QObject(parent), handle(INVALID_HANDLE_VALUE), - overlapped(this), + overlapped(nullptr), readBufferMaxSize(0), actualReadBufferSize(0), stopped(true), @@ -74,6 +74,7 @@ QWindowsPipeReader::QWindowsPipeReader(QObject *parent) QWindowsPipeReader::~QWindowsPipeReader() { stop(); + delete overlapped; } /*! @@ -95,14 +96,16 @@ void QWindowsPipeReader::stop() { stopped = true; if (readSequenceStarted) { - if (!CancelIoEx(handle, &overlapped)) { + overlapped->pipeReader = nullptr; + if (!CancelIoEx(handle, overlapped)) { const DWORD dwError = GetLastError(); if (dwError != ERROR_NOT_FOUND) { qErrnoWarning(dwError, "QWindowsPipeReader: CancelIoEx on handle %p failed.", handle); } } - waitForNotification(-1); + overlapped = nullptr; // The object will be deleted in the I/O callback. + readSequenceStarted = false; } } @@ -232,8 +235,10 @@ void QWindowsPipeReader::startAsyncRead() stopped = false; readSequenceStarted = true; - overlapped.clear(); - if (!ReadFileEx(handle, ptr, bytesToRead, &overlapped, &readFileCompleted)) { + if (!overlapped) + overlapped = new Overlapped(this); + overlapped->clear(); + if (!ReadFileEx(handle, ptr, bytesToRead, overlapped, &readFileCompleted)) { readSequenceStarted = false; const DWORD dwError = GetLastError(); @@ -260,7 +265,10 @@ void QWindowsPipeReader::readFileCompleted(DWORD errorCode, DWORD numberOfBytesT OVERLAPPED *overlappedBase) { Overlapped *overlapped = static_cast(overlappedBase); - overlapped->pipeReader->notified(errorCode, numberOfBytesTransfered); + if (overlapped->pipeReader) + overlapped->pipeReader->notified(errorCode, numberOfBytesTransfered); + else + delete overlapped; } /*! diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h index 74ff5250ac..e52aa4c33d 100644 --- a/src/corelib/io/qwindowspipereader_p.h +++ b/src/corelib/io/qwindowspipereader_p.h @@ -105,7 +105,7 @@ private: }; HANDLE handle; - Overlapped overlapped; + Overlapped *overlapped; qint64 readBufferMaxSize; QRingBuffer readBuffer; qint64 actualReadBufferSize; diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index d6ee4741e3..7eb6dd0389 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -56,7 +56,7 @@ void QWindowsPipeWriter::Overlapped::clear() QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent) : QObject(parent), handle(pipeWriteEnd), - overlapped(this), + overlapped(nullptr), numberOfBytesToWrite(0), pendingBytesWrittenValue(0), stopped(true), @@ -72,6 +72,7 @@ QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent) QWindowsPipeWriter::~QWindowsPipeWriter() { stop(); + delete overlapped; } bool QWindowsPipeWriter::waitForWrite(int msecs) @@ -122,7 +123,10 @@ void QWindowsPipeWriter::writeFileCompleted(DWORD errorCode, DWORD numberOfBytes OVERLAPPED *overlappedBase) { Overlapped *overlapped = static_cast(overlappedBase); - overlapped->pipeWriter->notified(errorCode, numberOfBytesTransfered); + if (overlapped->pipeWriter) + overlapped->pipeWriter->notified(errorCode, numberOfBytesTransfered); + else + delete overlapped; } /*! @@ -185,13 +189,15 @@ bool QWindowsPipeWriter::write(const QByteArray &ba) if (writeSequenceStarted) return false; - overlapped.clear(); + if (!overlapped) + overlapped = new Overlapped(this); + overlapped->clear(); buffer = ba; numberOfBytesToWrite = buffer.size(); stopped = false; writeSequenceStarted = true; if (!WriteFileEx(handle, buffer.constData(), numberOfBytesToWrite, - &overlapped, &writeFileCompleted)) { + overlapped, &writeFileCompleted)) { writeSequenceStarted = false; numberOfBytesToWrite = 0; buffer.clear(); @@ -208,14 +214,16 @@ void QWindowsPipeWriter::stop() bytesWrittenPending = false; pendingBytesWrittenValue = 0; if (writeSequenceStarted) { - if (!CancelIoEx(handle, &overlapped)) { + overlapped->pipeWriter = nullptr; + if (!CancelIoEx(handle, overlapped)) { const DWORD dwError = GetLastError(); if (dwError != ERROR_NOT_FOUND) { qErrnoWarning(dwError, "QWindowsPipeWriter: CancelIoEx on handle %p failed.", handle); } } - waitForNotification(-1); + overlapped = nullptr; // The object will be deleted in the I/O callback. + writeSequenceStarted = false; } } diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h index c43e986f34..c8252e2a4b 100644 --- a/src/corelib/io/qwindowspipewriter_p.h +++ b/src/corelib/io/qwindowspipewriter_p.h @@ -143,7 +143,7 @@ private: }; HANDLE handle; - Overlapped overlapped; + Overlapped *overlapped; QByteArray buffer; qint64 numberOfBytesToWrite; qint64 pendingBytesWrittenValue; -- cgit v1.2.3 From 9a69a1b969c114f7b4a21a5607b2ec70991dc7c7 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 22 Jun 2017 12:26:54 +0200 Subject: Doc: Fix snippet for QUrl::isValid() documentation qDebug(...) expects a const char *, not a QString. Change-Id: Ie4489c29440e328a732ed026eae3859eb8855ea5 Reviewed-by: Thiago Macieira Reviewed-by: Friedemann Kleint --- src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp index 805646c7d9..b2a2282085 100644 --- a/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp @@ -62,7 +62,7 @@ QUrl url = QUrl::fromEncoded("http://qt-project.org/List%20of%20holidays.xml"); //! [2] bool checkUrl(const QUrl &url) { if (!url.isValid()) { - qDebug(QString("Invalid URL: %1").arg(url.toString())); + qDebug("Invalid URL: %s", qUtf8Printable(url.toString())); return false; } -- cgit v1.2.3 From 54c2bfc9dbc445be94ba5031d96f93f497246744 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 20 Apr 2017 11:48:38 +0200 Subject: Doc: Clarify limitations of category filter As suggested by ogoffart. Change-Id: I15747869147819799b14dfe0670ff2225f76fc03 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qloggingcategory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 69af936bca..3eaf10c53e 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -411,8 +411,8 @@ QLoggingCategory *QLoggingCategory::defaultCategory() filter is free to change the respective category configuration with \l setEnabled(). - The filter might be called concurrently from different threads, and - therefore has to be reentrant. + The filter might be called from different threads, but never concurrently. + The filter shall not call any static functions of QLoggingCategory. Example: \snippet qloggingcategory/main.cpp 21 -- cgit v1.2.3 From 3f18dadeeb36e8add4f82f6e6b63373e1bac5e27 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 20 Apr 2017 11:00:46 +0200 Subject: Doc: QLoggingCategory::setEnabled() should only be called in filter Change-Id: Ib159c45ca259af125e48e3dfe59d64abc5f81f81 Reviewed-by: Thiago Macieira --- src/corelib/io/qloggingcategory.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 3eaf10c53e..4256d4b6e1 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -334,12 +334,11 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const /*! Changes the message type \a type for the category to \a enable. - \note Changes only affect the current QLoggingCategory object, and won't - change the settings of other objects for the same category name. - Use either \l setFilterRules() or \l installFilter() to change the - configuration globally. + This method is meant to be used only from inside a filter + installed by \l installFilter(). See \l {Configuring Categories} for + an overview on how to configure categories globally. - \note \c QtFatalMsg cannot be changed. It will always return \c true. + \note \c QtFatalMsg cannot be changed. It will always remain \c true. */ void QLoggingCategory::setEnabled(QtMsgType type, bool enable) { -- cgit v1.2.3 From c0bd7ade1aa49ed6877e5f13a74bcb72ff662062 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 9 Jul 2017 12:29:26 -0700 Subject: QFileSystemEngine::id/Windows: Use the volume ID too The MS documentation says that the high/low parts uniquely identify a file within a system, but they actually mean the filesystem. The details on how it's allocated make that clear. So we need the volume identifier. Change-Id: I658f552684924f8aa2cafffd14cfc03c5a09c0e9 Reviewed-by: Friedemann Kleint Reviewed-by: Kai Koehne Reviewed-by: Maurice Kalinowski --- src/corelib/io/qfilesystemengine_win.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index e4a7ea4891..5ed2671ab4 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -571,19 +571,21 @@ typedef struct _FILE_ID_INFO { // File ID for Windows up to version 7. static inline QByteArray fileId(HANDLE handle) { - QByteArray result; #ifndef Q_OS_WINRT BY_HANDLE_FILE_INFORMATION info; if (GetFileInformationByHandle(handle, &info)) { - result = QByteArray::number(uint(info.nFileIndexLow), 16); - result += ':'; - result += QByteArray::number(uint(info.nFileIndexHigh), 16); + char buffer[sizeof "01234567:0123456701234567"]; + qsnprintf(buffer, sizeof(buffer), "%lx:%08lx%08lx", + info.dwVolumeSerialNumber, + info.nFileIndexHigh, + info.nFileIndexLow); + return buffer; } #else // !Q_OS_WINRT Q_UNUSED(handle); Q_UNIMPLEMENTED(); #endif // Q_OS_WINRT - return result; + return QByteArray(); } // File ID for Windows starting from version 8. -- cgit v1.2.3 From f3205a49498d3084f46bc2c2abcd085c8436553b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Jun 2017 21:18:04 -0700 Subject: Merge qt_error_string and QSystemError This removes a lot of duplicated code that existed in both qglobal.cpp and qsystemerror.cpp, including the hack to get the correct strerror_r signature. This removes the incorrect use of EACCES, EMFILE, ENOENT, and ENOSPC from qt_error_string on Windows. qt_error_string is supposed to be used only with Win32 error codes from GetLastError(), despite there being a lot of uses in cross-platform and even Windows-specific code that pass errno constants. It may or may not work: that depends on whether the constants happen to match. ENOENT matches ERROR_FILE_NOT_FOUND and one could argue that ENOSPC matching ERROR_OUT_OF_PAPER is acceptable, but EMFILE isn't the same as ERROR_BAD_LENGTH nor is EACCES, ERROR_INVALID_DATA. Change-Id: I1eba2b016de74620bfc8fffd14cccb7f77f4b510 Reviewed-by: Friedemann Kleint Reviewed-by: Kai Koehne Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.cpp | 92 ------------------------------------- src/corelib/kernel/qsystemerror.cpp | 29 ++++++++++-- src/corelib/kernel/qsystemerror_p.h | 14 +++++- 3 files changed, 38 insertions(+), 97 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 9b76c72c0d..4223d2a3e1 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -3102,98 +3102,6 @@ Q_CORE_EXPORT unsigned int qt_int_sqrt(unsigned int n) void *qMemCopy(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); } void *qMemSet(void *dest, int c, size_t n) { return memset(dest, c, n); } -#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \ - defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L -namespace { - // There are two incompatible versions of strerror_r: - // a) the XSI/POSIX.1 version, which returns an int, - // indicating success or not - // b) the GNU version, which returns a char*, which may or may not - // be the beginning of the buffer we used - // The GNU libc manpage for strerror_r says you should use the XSI - // version in portable code. However, it's impossible to do that if - // _GNU_SOURCE is defined so we use C++ overloading to decide what to do - // depending on the return type - static inline Q_DECL_UNUSED QString fromstrerror_helper(int, const QByteArray &buf) - { - return QString::fromLocal8Bit(buf.constData()); - } - static inline Q_DECL_UNUSED QString fromstrerror_helper(const char *str, const QByteArray &) - { - return QString::fromLocal8Bit(str); - } -} -#endif - -QString qt_error_string(int errorCode) -{ - const char *s = 0; - QString ret; - if (errorCode == -1) { -#if defined(Q_OS_WIN) - errorCode = GetLastError(); -#else - errorCode = errno; -#endif - } - switch (errorCode) { - case 0: - break; - case EACCES: - s = QT_TRANSLATE_NOOP("QIODevice", "Permission denied"); - break; - case EMFILE: - s = QT_TRANSLATE_NOOP("QIODevice", "Too many open files"); - break; - case ENOENT: - s = QT_TRANSLATE_NOOP("QIODevice", "No such file or directory"); - break; - case ENOSPC: - s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device"); - break; - default: { -#if defined(Q_OS_WIN) - // Retrieve the system error message for the last-error code. -# ifndef Q_OS_WINRT - wchar_t *string = 0; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPWSTR)&string, - 0, - NULL); - ret = QString::fromWCharArray(string); - LocalFree((HLOCAL)string); -# else // !Q_OS_WINRT - __declspec(thread) static wchar_t errorString[4096]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - errorString, - ARRAYSIZE(errorString), - NULL); - ret = QString::fromWCharArray(errorString); -# endif // Q_OS_WINRT - - if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND) - ret = QString::fromLatin1("The specified module could not be found."); -#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) - QByteArray buf(1024, '\0'); - ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf); -#else - ret = QString::fromLocal8Bit(strerror(errorCode)); -#endif - break; } - } - if (s) - // ######## this breaks moc build currently -// ret = QCoreApplication::translate("QIODevice", s); - ret = QString::fromLatin1(s); - return ret.trimmed(); -} - // In the C runtime on all platforms access to the environment is not thread-safe. We // add thread-safety for the Qt wrappers. static QBasicMutex environmentMutex; diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp index 3899f24d3b..6583838a9f 100644 --- a/src/corelib/kernel/qsystemerror.cpp +++ b/src/corelib/kernel/qsystemerror.cpp @@ -101,6 +101,8 @@ static QString windowsErrorString(int errorCode) if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND) ret = QString::fromLatin1("The specified module could not be found."); + if (ret.endsWith(QLatin1String("\r\n"))) + ret.chop(2); return ret; } #endif @@ -126,7 +128,7 @@ static QString standardLibraryErrorString(int errorCode) break; default: { #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) - QByteArray buf(1024, '\0'); + QByteArray buf(1024, Qt::Uninitialized); ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf); #else ret = QString::fromLocal8Bit(strerror(errorCode)); @@ -141,7 +143,7 @@ static QString standardLibraryErrorString(int errorCode) return ret.trimmed(); } -QString QSystemError::toString() const +QString QSystemError::string(ErrorScope errorScope, int errorCode) { switch(errorScope) { case NativeError: @@ -161,5 +163,26 @@ QString QSystemError::toString() const } } -QT_END_NAMESPACE +QString QSystemError::stdString(int errorCode) +{ + return standardLibraryErrorString(errorCode == -1 ? errno : errorCode); +} + +#ifdef Q_OS_WIN +QString QSystemError::windowsString(int errorCode) +{ + return windowsErrorString(errorCode == -1 ? GetLastError() : errorCode); +} +QString qt_error_string(int code) +{ + return windowsErrorString(code == -1 ? GetLastError() : code); +} +#else +QString qt_error_string(int code) +{ + return standardLibraryErrorString(code == -1 ? errno : code); +} +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qsystemerror_p.h b/src/corelib/kernel/qsystemerror_p.h index 440b763149..1d8c253f53 100644 --- a/src/corelib/kernel/qsystemerror_p.h +++ b/src/corelib/kernel/qsystemerror_p.h @@ -69,10 +69,16 @@ public: inline QSystemError(int error, ErrorScope scope); inline QSystemError(); - QString toString() const; + inline QString toString() const; inline ErrorScope scope() const; inline int error() const; + static QString string(ErrorScope errorScope, int errorCode); + static QString stdString(int errorCode = -1); +#ifdef Q_OS_WIN + static QString windowsString(int errorCode = -1); +#endif + //data members int errorCode; ErrorScope errorScope; @@ -90,6 +96,11 @@ QSystemError::QSystemError() } +QString QSystemError::toString() const +{ + return string(errorScope, errorCode); +} + QSystemError::ErrorScope QSystemError::scope() const { return errorScope; @@ -100,7 +111,6 @@ int QSystemError::error() const return errorCode; } - QT_END_NAMESPACE #endif // QSYSTEMERROR_P_H -- cgit v1.2.3 From bf410ed529789f89a63af6a35bb06837b31b95a2 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Jun 2017 22:14:53 -0700 Subject: Convert improper uses of qt_error_string() to QSystemError::stdString() On Windows, qt_error_string() returns the string corresponding to the Win32 API, not an errno. Replace those uses for a function that works for errno values. Change-Id: I1eba2b016de74620bfc8fffd14ccce6162bafdca Reviewed-by: Lars Knoll --- src/corelib/io/qfsfileengine.cpp | 22 +++++++++++----------- src/corelib/io/qfsfileengine_win.cpp | 4 ++-- src/corelib/io/qresource.cpp | 3 ++- src/corelib/plugin/qlibrary.cpp | 3 ++- 4 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 0b9cd0557f..88e8baedca 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -268,7 +268,7 @@ bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh) if (ret != 0) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, - qt_error_string(int(errno))); + QSystemError::stdString()); this->openMode = QIODevice::NotOpen; this->fh = 0; @@ -332,7 +332,7 @@ bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode, int fd) if (ret == -1) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, - qt_error_string(int(errno))); + QSystemError::stdString()); this->openMode = QIODevice::NotOpen; this->fd = -1; @@ -391,7 +391,7 @@ bool QFSFileEnginePrivate::closeFdFh() if (!flushed || !closed) { if (flushed) { // If not flushed, we want the flush error to fall through. - q->setError(QFile::UnspecifiedError, qt_error_string(errno)); + q->setError(QFile::UnspecifiedError, QSystemError::stdString()); } return false; } @@ -443,7 +443,7 @@ bool QFSFileEnginePrivate::flushFh() if (ret != 0) { q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, - qt_error_string(errno)); + QSystemError::stdString()); return false; } return true; @@ -539,14 +539,14 @@ bool QFSFileEnginePrivate::seekFdFh(qint64 pos) } while (ret != 0 && errno == EINTR); if (ret != 0) { - q->setError(QFile::ReadError, qt_error_string(int(errno))); + q->setError(QFile::ReadError, QSystemError::stdString()); return false; } } else { // Unbuffered stdio mode. if (QT_LSEEK(fd, QT_OFF_T(pos), SEEK_SET) == -1) { qWarning("QFile::at: Cannot set file position %lld", pos); - q->setError(QFile::PositionError, qt_error_string(errno)); + q->setError(QFile::PositionError, QSystemError::stdString()); return false; } } @@ -588,7 +588,7 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len) Q_Q(QFSFileEngine); if (len < 0 || len != qint64(size_t(len))) { - q->setError(QFile::ReadError, qt_error_string(EINVAL)); + q->setError(QFile::ReadError, QSystemError::stdString(EINVAL)); return -1; } @@ -634,7 +634,7 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len) if (!eof && readBytes == 0) { readBytes = -1; - q->setError(QFile::ReadError, qt_error_string(errno)); + q->setError(QFile::ReadError, QSystemError::stdString()); } return readBytes; @@ -680,7 +680,7 @@ qint64 QFSFileEnginePrivate::readLineFdFh(char *data, qint64 maxlen) // solves this. if (!fgets(data, int(maxlen + 1), fh)) { if (!feof(fh)) - q->setError(QFile::ReadError, qt_error_string(int(errno))); + q->setError(QFile::ReadError, QSystemError::stdString()); return -1; // error } @@ -719,7 +719,7 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len) Q_Q(QFSFileEngine); if (len < 0 || len != qint64(size_t(len))) { - q->setError(QFile::WriteError, qt_error_string(EINVAL)); + q->setError(QFile::WriteError, QSystemError::stdString(EINVAL)); return -1; } @@ -756,7 +756,7 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len) if (len && writtenBytes == 0) { writtenBytes = -1; - q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, qt_error_string(errno)); + q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, QSystemError::stdString()); } else { // reset the cached size, if any metaData.clearFlags(QFileSystemMetaData::SizeAttribute); diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 7d16e59195..fb3cdd3981 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -252,7 +252,7 @@ qint64 QFSFileEnginePrivate::nativeSize() const filled = doStat(QFileSystemMetaData::SizeAttribute); if (!filled) { - thatQ->setError(QFile::UnspecifiedError, qt_error_string(errno)); + thatQ->setError(QFile::UnspecifiedError, QSystemError::stdString()); return 0; } return metaData.size(); @@ -319,7 +319,7 @@ qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 maxlen) if (fh || fd != -1) { // stdio / stdlib mode. if (fh && nativeIsSequential() && feof(fh)) { - q->setError(QFile::ReadError, qt_error_string(int(errno))); + q->setError(QFile::ReadError, QSystemError::stdString()); return -1; } diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 32639759e4..4e7120a3b8 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -53,6 +53,7 @@ #include #include #include "private/qabstractfileengine_p.h" +#include "private/qsystemerror_p.h" #ifdef Q_OS_UNIX # include "private/qcore_unix_p.h" @@ -1284,7 +1285,7 @@ bool QResourceFileEngine::open(QIODevice::OpenMode flags) return false; d->uncompress(); if (!d->resource.isValid()) { - d->errorString = qt_error_string(ENOENT); + d->errorString = QSystemError::stdString(ENOENT); return false; } return true; diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 3d04d0802d..ebad7f1751 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #ifdef Q_OS_MAC # include #endif @@ -237,7 +238,7 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib) lib->errorString = file.errorString(); if (qt_debug_component()) { qWarning("%s: %s", (const char*) QFile::encodeName(library), - qPrintable(qt_error_string(errno))); + qPrintable(QSystemError::stdString())); } return false; } -- cgit v1.2.3 From f9bfc8b91cd8ea755808751ab6268e37ffd6c17a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 7 Jul 2017 13:16:25 -0700 Subject: QSystemError: Make it format unknown Windows messages Can happen if we're using HRESULT from weird facilities. Change-Id: I3d10feaa2e5854ff3c01b32dbd068309e5131d1b Reviewed-by: Friedemann Kleint --- src/corelib/kernel/qsystemerror.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp index 6583838a9f..fc825257ec 100644 --- a/src/corelib/kernel/qsystemerror.cpp +++ b/src/corelib/kernel/qsystemerror.cpp @@ -103,6 +103,9 @@ static QString windowsErrorString(int errorCode) ret = QString::fromLatin1("The specified module could not be found."); if (ret.endsWith(QLatin1String("\r\n"))) ret.chop(2); + if (ret.isEmpty()) + ret = QString::fromLatin1("Unknown error 0x%1.") + .arg(unsigned(errorCode), 8, 16, QLatin1Char('0')); return ret; } #endif -- cgit v1.2.3 From ad3b41a06d9ba7219c79b5548c5b11698787288d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Jun 2017 12:55:54 -0700 Subject: QFile::rename: use the open file's ID, instead of using the file name To do that, we needed to add virtual id() in QAbstractFileEngine and override it in QFSFileEngine. It might be useful to return other types of IDs for the other file engines, but this commit does not attempt that just yet. Change-Id: I1eba2b016de74620bfc8fffd14ccafe0762b3c38 Reviewed-by: Friedemann Kleint Reviewed-by: Thiago Macieira --- src/corelib/io/qabstractfileengine.cpp | 11 +++++++++++ src/corelib/io/qabstractfileengine_p.h | 1 + src/corelib/io/qfile.cpp | 4 +++- src/corelib/io/qfilesystemengine_p.h | 2 ++ src/corelib/io/qfilesystemengine_unix.cpp | 14 ++++++++++++++ src/corelib/io/qfilesystemengine_win.cpp | 10 ++++++++-- src/corelib/io/qfsfileengine_p.h | 1 + src/corelib/io/qfsfileengine_unix.cpp | 8 ++++++++ src/corelib/io/qfsfileengine_win.cpp | 18 ++++++++++++++++++ 9 files changed, 66 insertions(+), 3 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index 9606ec68e9..89727673d3 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -677,6 +677,17 @@ bool QAbstractFileEngine::setPermissions(uint perms) return false; } +/*! + \since 5.9 + + Return an identifier that (hopefully) uniquely identifies this file in the + system. Returns an invalid QByteArray() if that cannot be calculated. +*/ +QByteArray QAbstractFileEngine::id() const +{ + return QByteArray(); +} + /*! Return the file engine's current file name in the format specified by \a file. diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h index 48b3dec324..58fa776e49 100644 --- a/src/corelib/io/qabstractfileengine_p.h +++ b/src/corelib/io/qabstractfileengine_p.h @@ -141,6 +141,7 @@ public: virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const; virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const; virtual bool setPermissions(uint perms); + virtual QByteArray id() const; virtual QString fileName(FileName file=DefaultName) const; virtual uint ownerId(FileOwner) const; virtual QString owner(FileOwner) const; diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index a840307145..f7e711a7cf 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -570,7 +570,9 @@ QFile::rename(const QString &newName) // Note: this does not take file engines into account. QByteArray targetId = QFileSystemEngine::id(QFileSystemEntry(newName)); if (!targetId.isNull()) { - QByteArray fileId = QFileSystemEngine::id(QFileSystemEntry(d->fileName)); + QByteArray fileId = d->fileEngine ? + d->fileEngine->id() : + QFileSystemEngine::id(QFileSystemEntry(d->fileName)); if (fileId != targetId || d->fileName.compare(newName, Qt::CaseInsensitive)) { // ### Race condition. If a file is moved in after this, it /will/ be // overwritten. On Unix, the proper solution is to use hardlinks: diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h index 196ed8df69..e3e52f6eaa 100644 --- a/src/corelib/io/qfilesystemengine_p.h +++ b/src/corelib/io/qfilesystemengine_p.h @@ -92,6 +92,7 @@ public: QFileSystemMetaData::MetaDataFlags what); #if defined(Q_OS_UNIX) static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags + static QByteArray id(int fd); static bool setPermissions(int fd, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data = nullptr); #endif @@ -104,6 +105,7 @@ public: QFileSystemMetaData::MetaDataFlags what); static bool fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what); + static QByteArray id(HANDLE fHandle); static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own); static QString nativeAbsoluteFilePath(const QString &path); #endif diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index c3906c3207..6640e2b7e7 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -348,6 +348,20 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry) return result; } +//static +QByteArray QFileSystemEngine::id(int id) +{ + QT_STATBUF statResult; + if (QT_FSTAT(id, &statResult)) { + qErrnoWarning("fstat() failed for fd %d", id); + return QByteArray(); + } + QByteArray result = QByteArray::number(quint64(statResult.st_dev), 16); + result += ':'; + result += QByteArray::number(quint64(statResult.st_ino)); + return result; +} + //static QString QFileSystemEngine::resolveUserName(uint userId) { diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 5ed2671ab4..1cb4c75699 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -621,13 +621,19 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry) FILE_SHARE_READ, OPEN_EXISTING, NULL); #endif // Q_OS_WINRT if (handle != INVALID_HANDLE_VALUE) { - result = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ? - fileIdWin8(handle) : fileId(handle); + result = id(handle); CloseHandle(handle); } return result; } +//static +QByteArray QFileSystemEngine::id(HANDLE fHandle) +{ + return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ? + fileIdWin8(HANDLE(fHandle)) : fileId(HANDLE(fHandle)); +} + //static QString QFileSystemEngine::owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own) { diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 593ecc2687..ab9ad3aa6b 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -93,6 +93,7 @@ public: QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const Q_DECL_OVERRIDE; FileFlags fileFlags(FileFlags type) const Q_DECL_OVERRIDE; bool setPermissions(uint perms) Q_DECL_OVERRIDE; + QByteArray id() const override; QString fileName(FileName file) const Q_DECL_OVERRIDE; uint ownerId(FileOwner) const Q_DECL_OVERRIDE; QString owner(FileOwner) const Q_DECL_OVERRIDE; diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 3f4f593d81..c613368a91 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -596,6 +596,14 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const return ret; } +QByteArray QFSFileEngine::id() const +{ + Q_D(const QFSFileEngine); + if (d->fd != -1) + return QFileSystemEngine::id(d->fd); + return QFileSystemEngine::id(d->fileEntry); +} + QString QFSFileEngine::fileName(FileName file) const { Q_D(const QFSFileEngine); diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index fb3cdd3981..7a010df671 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -718,6 +718,24 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil return ret; } +QByteArray QFSFileEngine::id() const +{ + Q_D(const QFSFileEngine); + HANDLE h = d->fileHandle; + if (h == INVALID_HANDLE_VALUE) { + int localFd = d->fd; + if (d->fh && d->fileEntry.isEmpty()) + localFd = QT_FILENO(d->fh); + if (localFd != -1) + h = HANDLE(_get_osfhandle(localFd)); + } + if (h != INVALID_HANDLE_VALUE) + return QFileSystemEngine::id(h); + + // file is not open, try by path + return QFileSystemEngine::id(d->fileEntry); +} + QString QFSFileEngine::fileName(FileName file) const { Q_D(const QFSFileEngine); -- cgit v1.2.3