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 <Friedemann.Kleint@qt.io> Reviewed-by: Kai Koehne <kai.koehne@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
c0bd7ade1a
commit
f3205a4949
@ -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 *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); }
|
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
|
// In the C runtime on all platforms access to the environment is not thread-safe. We
|
||||||
// add thread-safety for the Qt wrappers.
|
// add thread-safety for the Qt wrappers.
|
||||||
static QBasicMutex environmentMutex;
|
static QBasicMutex environmentMutex;
|
||||||
|
@ -101,6 +101,8 @@ static QString windowsErrorString(int errorCode)
|
|||||||
|
|
||||||
if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
|
if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
|
||||||
ret = QString::fromLatin1("The specified module could not be found.");
|
ret = QString::fromLatin1("The specified module could not be found.");
|
||||||
|
if (ret.endsWith(QLatin1String("\r\n")))
|
||||||
|
ret.chop(2);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -126,7 +128,7 @@ static QString standardLibraryErrorString(int errorCode)
|
|||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
|
#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);
|
ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf);
|
||||||
#else
|
#else
|
||||||
ret = QString::fromLocal8Bit(strerror(errorCode));
|
ret = QString::fromLocal8Bit(strerror(errorCode));
|
||||||
@ -141,7 +143,7 @@ static QString standardLibraryErrorString(int errorCode)
|
|||||||
return ret.trimmed();
|
return ret.trimmed();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QSystemError::toString() const
|
QString QSystemError::string(ErrorScope errorScope, int errorCode)
|
||||||
{
|
{
|
||||||
switch(errorScope) {
|
switch(errorScope) {
|
||||||
case NativeError:
|
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
|
||||||
|
@ -69,10 +69,16 @@ public:
|
|||||||
inline QSystemError(int error, ErrorScope scope);
|
inline QSystemError(int error, ErrorScope scope);
|
||||||
inline QSystemError();
|
inline QSystemError();
|
||||||
|
|
||||||
QString toString() const;
|
inline QString toString() const;
|
||||||
inline ErrorScope scope() const;
|
inline ErrorScope scope() const;
|
||||||
inline int error() 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
|
//data members
|
||||||
int errorCode;
|
int errorCode;
|
||||||
ErrorScope errorScope;
|
ErrorScope errorScope;
|
||||||
@ -90,6 +96,11 @@ QSystemError::QSystemError()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QSystemError::toString() const
|
||||||
|
{
|
||||||
|
return string(errorScope, errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
QSystemError::ErrorScope QSystemError::scope() const
|
QSystemError::ErrorScope QSystemError::scope() const
|
||||||
{
|
{
|
||||||
return errorScope;
|
return errorScope;
|
||||||
@ -100,7 +111,6 @@ int QSystemError::error() const
|
|||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QSYSTEMERROR_P_H
|
#endif // QSYSTEMERROR_P_H
|
||||||
|
@ -2303,7 +2303,11 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
|
|||||||
QTest::newRow("include(): fail")
|
QTest::newRow("include(): fail")
|
||||||
<< "include(include/nope.pri): OK = 1"
|
<< "include(include/nope.pri): OK = 1"
|
||||||
<< "OK = UNDEF"
|
<< "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"
|
<< "Cannot read " + m_indir + "/include/nope.pri: No such file or directory"
|
||||||
|
#endif
|
||||||
<< true;
|
<< true;
|
||||||
|
|
||||||
QTest::newRow("include(): silent fail")
|
QTest::newRow("include(): silent fail")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user