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 +++++- tests/auto/tools/qmakelib/evaltest.cpp | 4 ++ 4 files changed, 42 insertions(+), 97 deletions(-) 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 diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index 4e215b8570..03fd4753fd 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -2303,7 +2303,11 @@ void tst_qmakelib::addTestFunctions(const QString &qindir) QTest::newRow("include(): fail") << "include(include/nope.pri): OK = 1" << "OK = UNDEF" +#ifdef Q_OS_WIN + << "Cannot read " + m_indir + "/include/nope.pri: The system cannot find the file specified." +#else << "Cannot read " + m_indir + "/include/nope.pri: No such file or directory" +#endif << true; QTest::newRow("include(): silent fail") -- cgit v1.2.3