1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <qglobal.h>
41#include "qsystemerror_p.h"
42#include <errno.h>
43#if defined(Q_CC_MSVC)
44# include <crtdbg.h>
45#endif
46#ifdef Q_OS_WIN
47# include <qt_windows.h>
48#endif
49
50QT_BEGIN_NAMESPACE
51
52#if !defined(Q_OS_WIN) && QT_CONFIG(thread) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
53 defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L
54namespace {
55 // There are two incompatible versions of strerror_r:
56 // a) the XSI/POSIX.1 version, which returns an int,
57 // indicating success or not
58 // b) the GNU version, which returns a char*, which may or may not
59 // be the beginning of the buffer we used
60 // The GNU libc manpage for strerror_r says you should use the XSI
61 // version in portable code. However, it's impossible to do that if
62 // _GNU_SOURCE is defined so we use C++ overloading to decide what to do
63 // depending on the return type
64 static inline Q_DECL_UNUSED QString fromstrerror_helper(int, const QByteArray &buf)
65 {
66 return QString::fromLocal8Bit(buf);
67 }
68 static inline Q_DECL_UNUSED QString fromstrerror_helper(const char *str, const QByteArray &)
69 {
70 return QString::fromLocal8Bit(str);
71 }
72}
73#endif
74
75#ifdef Q_OS_WIN
76static QString windowsErrorString(int errorCode)
77{
78 QString ret;
79#ifndef Q_OS_WINRT
80 wchar_t *string = 0;
81 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
82 NULL,
83 errorCode,
84 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
85 (LPWSTR)&string,
86 0,
87 NULL);
88 ret = QString::fromWCharArray(string);
89 LocalFree((HLOCAL)string);
90#else
91 wchar_t errorString[1024];
92 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
93 NULL,
94 errorCode,
95 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
96 (LPWSTR)&errorString,
97 sizeof(errorString)/sizeof(wchar_t),
98 NULL);
99 ret = QString::fromWCharArray(errorString);
100#endif // Q_OS_WINRT
101
102 if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
103 ret = QString::fromLatin1("The specified module could not be found.");
104 if (ret.endsWith(QLatin1String("\r\n")))
105 ret.chop(2);
106 if (ret.isEmpty())
107 ret = QString::fromLatin1("Unknown error 0x%1.")
108 .arg(unsigned(errorCode), 8, 16, QLatin1Char('0'));
109 return ret;
110}
111#endif
112
113static QString standardLibraryErrorString(int errorCode)
114{
115 const char *s = nullptr;
116 QString ret;
117 switch (errorCode) {
118 case 0:
119 break;
120 case EACCES:
121 s = QT_TRANSLATE_NOOP("QIODevice", "Permission denied");
122 break;
123 case EMFILE:
124 s = QT_TRANSLATE_NOOP("QIODevice", "Too many open files");
125 break;
126 case ENOENT:
127 s = QT_TRANSLATE_NOOP("QIODevice", "No such file or directory");
128 break;
129 case ENOSPC:
130 s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device");
131 break;
132 default: {
133 #if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
134 QByteArray buf(1024, Qt::Uninitialized);
135 ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf);
136 #else
137 ret = QString::fromLocal8Bit(str: strerror(errnum: errorCode));
138 #endif
139 break; }
140 }
141 if (s) {
142 // ######## this breaks moc build currently
143 // ret = QCoreApplication::translate("QIODevice", s);
144 ret = QString::fromLatin1(str: s);
145 }
146 return ret.trimmed();
147}
148
149QString QSystemError::string(ErrorScope errorScope, int errorCode)
150{
151 switch(errorScope) {
152 case NativeError:
153#if defined (Q_OS_WIN)
154 return windowsErrorString(errorCode);
155#endif // else unix: native and standard library are the same
156 case StandardLibraryError:
157 return standardLibraryErrorString(errorCode);
158 default:
159 qWarning(msg: "invalid error scope");
160 Q_FALLTHROUGH();
161 case NoError:
162 return QLatin1String("No error");
163 }
164}
165
166QString QSystemError::stdString(int errorCode)
167{
168 return standardLibraryErrorString(errorCode: errorCode == -1 ? errno : errorCode);
169}
170
171#ifdef Q_OS_WIN
172QString QSystemError::windowsString(int errorCode)
173{
174 return windowsErrorString(errorCode == -1 ? GetLastError() : errorCode);
175}
176
177QString qt_error_string(int code)
178{
179 return windowsErrorString(code == -1 ? GetLastError() : code);
180}
181#else
182QString qt_error_string(int code)
183{
184 return standardLibraryErrorString(errorCode: code == -1 ? errno : code);
185}
186#endif
187
188QT_END_NAMESPACE
189

source code of qtbase/src/corelib/kernel/qsystemerror.cpp