1 /* $Id: ncbi_strerror.c 602352 2020-02-21 18:08:17Z lavr $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: Pavel Ivanov, Anton Lavrentiev, Denis Vakatov
27 *
28 * File Description:
29 * errno->text conversion helper
30 */
31
32
33 #ifdef NCBI_INCLUDE_STRERROR_C
34
35
36 # ifdef _FREETDS_LIBRARY_SOURCE
37
38 # include "../impl/ncbi_ftds_ver.h"
39 # define s_StrError s_StrErrorInternal
40 # define UTIL_TcharToUtf8 NCBI_FTDS_VERSION_NAME(UTIL_TcharToUtf8_ftds)
41 # define UTIL_ReleaseBufferOnHeap \
42 NCBI_FTDS_VERSION_NAME(UTIL_ReleaseBufferOnHeap_ftds)
43
44 # endif /*_FREETDS_LIBRARY_SOURCE*/
45
46
47 # if defined(NCBI_OS_MSWIN) && defined(_UNICODE)
48
s_WinStrdup(const char * str)49 static const char* s_WinStrdup(const char* str)
50 {
51 size_t n = strlen(str);
52 char* s = (char*) LocalAlloc(LMEM_FIXED, ++n * sizeof(*s));
53 return s ? (const char*) memcpy(s, str, n) : 0;
54 }
55 # define ERR_STRDUP(s) s_WinStrdup(s)
56
UTIL_TcharToUtf8(const TCHAR * str)57 extern const char* UTIL_TcharToUtf8(const TCHAR* str)
58 {
59 char* s = NULL;
60 if (str) {
61 /* Note "-1" means to consume all input including the trailing NUL */
62 int n = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
63 if (n > 0) {
64 s = (char*) LocalAlloc(LMEM_FIXED, n * sizeof(*s));
65 if (s)
66 WideCharToMultiByte(CP_UTF8, 0, str, -1, s, n, NULL, NULL);
67 }
68 }
69 return s;
70 }
71
72 # ifndef UTIL_ReleaseBuffer(x)
73 # define UTIL_ReleaseBuffer(x) UTIL_ReleaseBufferOnHeap(x)
74 # endif
75
76 # else /*NCBI_OS_MSWIN && _UNICODE*/
77
78 # define ERR_STRDUP(s) strdup(s)
79
80 # ifdef UTIL_TcharToUtf8
81 # undef UTIL_TcharToUtf8
82 # endif
83 # define UTIL_TcharToUtf8(x) strdup(x)
84
85 # ifdef UTIL_ReleaseBuffer
86 # undef UTIL_ReleaseBuffer
87 # endif
88 # define UTIL_ReleaseBuffer(x) free((void*)(x))
89
90 # endif /*NCBI_OS_MSWIN && _UNICODE*/
91
92
93 # ifdef NCBI_OS_MSWIN
94
UTIL_ReleaseBufferOnHeap(const void * ptr)95 extern void UTIL_ReleaseBufferOnHeap(const void* ptr)
96 {
97 if (ptr)
98 LocalFree((HLOCAL) ptr);
99 }
100
101 # endif /*NCBI_OS_MSWIN*/
102
103
s_StrErrorInternal(int error)104 static const char* s_StrErrorInternal(int error)
105 {
106 static const struct {
107 int errnum;
108 const char* errstr;
109 } errmap[] = {
110 # ifdef NCBI_OS_MSWIN
111 {WSAEINTR, "Interrupted system call"},
112 {WSAEBADF, "Bad file number"},
113 {WSAEACCES, "Access denied"},
114 {WSAEFAULT, "Segmentation fault"},
115 {WSAEINVAL, "Invalid agrument"},
116 {WSAEMFILE, "Too many open files"},
117 /*
118 * Windows Sockets definitions of regular Berkeley error constants
119 */
120 {WSAEWOULDBLOCK, "Resource temporarily unavailable"},
121 {WSAEINPROGRESS, "Operation now in progress"},
122 {WSAEALREADY, "Operation already in progress"},
123 {WSAENOTSOCK, "Not a socket"},
124 {WSAEDESTADDRREQ, "Destination address required"},
125 {WSAEMSGSIZE, "Invalid message size"},
126 {WSAEPROTOTYPE, "Wrong protocol type"},
127 {WSAENOPROTOOPT, "Bad protocol option"},
128 {WSAEPROTONOSUPPORT, "Protocol not supported"},
129 {WSAESOCKTNOSUPPORT, "Socket type not supported"},
130 {WSAEOPNOTSUPP, "Operation not supported"},
131 {WSAEPFNOSUPPORT, "Protocol family not supported"},
132 {WSAEAFNOSUPPORT, "Address family not supported"},
133 {WSAEADDRINUSE, "Address already in use"},
134 {WSAEADDRNOTAVAIL, "Cannot assign requested address"},
135 {WSAENETDOWN, "Network is down"},
136 {WSAENETUNREACH, "Network is unreachable"},
137 {WSAENETRESET, "Connection dropped on network reset"},
138 {WSAECONNABORTED, "Software caused connection abort"},
139 {WSAECONNRESET, "Connection reset by peer"},
140 {WSAENOBUFS, "No buffer space available"},
141 {WSAEISCONN, "Socket is already connected"},
142 {WSAENOTCONN, "Socket is not connected"},
143 {WSAESHUTDOWN, "Cannot send after socket shutdown"},
144 {WSAETOOMANYREFS, "Too many references"},
145 {WSAETIMEDOUT, "Operation timed out"},
146 {WSAECONNREFUSED, "Connection refused"},
147 {WSAELOOP, "Infinite loop"},
148 {WSAENAMETOOLONG, "Name too long"},
149 {WSAEHOSTDOWN, "Host is down"},
150 {WSAEHOSTUNREACH, "Host unreachable"},
151 {WSAENOTEMPTY, "Not empty"},
152 {WSAEPROCLIM, "Too many processes"},
153 {WSAEUSERS, "Too many users"},
154 {WSAEDQUOT, "Quota exceeded"},
155 {WSAESTALE, "Stale descriptor"},
156 {WSAEREMOTE, "Remote error"},
157 /*
158 * Extended Windows Sockets error constant definitions
159 */
160 {WSASYSNOTREADY, "Network subsystem is unavailable"},
161 {WSAVERNOTSUPPORTED, "Winsock.dll version out of range"},
162 {WSANOTINITIALISED, "Not yet initialized"},
163 {WSAEDISCON, "Graceful shutdown in progress"},
164 # ifdef WSAENOMORE
165 /*NB: replaced with WSA_E_NO_MORE*/
166 {WSAENOMORE, "No more data available"},
167 # endif /*WSAENOMORE*/
168 # ifdef WSA_E_NO_MORE
169 {WSA_E_NO_MORE, "No more data available"},
170 # endif /*WSA_E_NO_MORE*/
171 # ifdef WSAECANCELLED
172 /*NB: replaced with WSA_E_CANCELLED*/
173 {WSAECANCELLED, "Call has been cancelled"},
174 # endif /*WSAECANCELLED*/
175 # ifdef WSA_E_CANCELLED
176 {WSA_E_CANCELLED, "Call has been cancelled"},
177 # endif /*WSA_E_CANCELLED*/
178 {WSAEINVALIDPROCTABLE, "Invalid procedure table"},
179 {WSAEINVALIDPROVIDER, "Invalid provider version number"},
180 {WSAEPROVIDERFAILEDINIT,"Cannot init provider"},
181 {WSASYSCALLFAILURE, "System call failed"},
182 {WSASERVICE_NOT_FOUND, "Service not found"},
183 {WSATYPE_NOT_FOUND, "Class type not found"},
184 {WSAEREFUSED, "Query refused"},
185 /*
186 * WinSock 2 extension
187 */
188 # ifdef WSA_IO_PENDING
189 {WSA_IO_PENDING, "Operation has been queued"},
190 # endif /*WSA_IO_PENDING*/
191 # ifdef WSA_IO_INCOMPLETE
192 {WSA_IO_INCOMPLETE, "Operation still in progress"},
193 # endif /*WSA_IO_INCOMPLETE*/
194 # ifdef WSA_INVALID_HANDLE
195 {WSA_INVALID_HANDLE, "Invalid handle"},
196 # endif /*WSA_INVALID_HANDLE*/
197 # ifdef WSA_INVALID_PARAMETER
198 {WSA_INVALID_PARAMETER, "Invalid parameter"},
199 # endif /*WSA_INVALID_PARAMETER*/
200 # ifdef WSA_NOT_ENOUGH_MEMORY
201 {WSA_NOT_ENOUGH_MEMORY, "Out of memory"},
202 # endif /*WSA_NOT_ENOUGH_MEMORY*/
203 # ifdef WSA_OPERATION_ABORTED
204 {WSA_OPERATION_ABORTED, "Operation aborted"},
205 # endif /*WSA_OPERATION_ABORTED*/
206 # endif /*NCBI_OS_MSWIN*/
207 # ifdef NCBI_OS_MSWIN
208 # define EAI_BASE 0
209 # else
210 # define EAI_BASE 100000
211 # endif /*NCBI_OS_MSWIN*/
212 # ifdef EAI_ADDRFAMILY
213 {EAI_ADDRFAMILY + EAI_BASE,
214 "Address family not supported"},
215 # endif /*EAI_ADDRFAMILY*/
216 # ifdef EAI_AGAIN
217 {EAI_AGAIN + EAI_BASE,
218 "Temporary failure in name resolution"},
219 # endif /*EAI_AGAIN*/
220 # ifdef EAI_BADFLAGS
221 {EAI_BADFLAGS + EAI_BASE,
222 "Invalid value for lookup flags"},
223 # endif /*EAI_BADFLAGS*/
224 # ifdef EAI_FAIL
225 {EAI_FAIL + EAI_BASE,
226 "Non-recoverable failure in name resolution"},
227 # endif /*EAI_FAIL*/
228 # ifdef EAI_FAMILY
229 {EAI_FAMILY + EAI_BASE,
230 "Address family not supported"},
231 # endif /*EAI_FAMILY*/
232 # ifdef EAI_MEMORY
233 {EAI_MEMORY + EAI_BASE,
234 "Memory allocation failure"},
235 # endif /*EAI_MEMORY*/
236 # ifdef EAI_NODATA
237 # if EAI_NODATA != EAI_NONAME
238 {EAI_NODATA + EAI_BASE,
239 "No address associated with nodename"},
240 # endif /*EAI_NODATA!=EAI_NONAME*/
241 # endif /*EAI_NODATA*/
242 # ifdef EAI_NONAME
243 {EAI_NONAME + EAI_BASE,
244 "Host and/or service name unknown"},
245 # endif /*EAI_NONAME*/
246 # ifdef EAI_OVERFLOW
247 {EAI_OVERFLOW + EAI_BASE,
248 "Argument buffer overflow"},
249 # endif /*EAI_OVERFLOW*/
250 # ifdef EAI_SERVICE
251 {EAI_SERVICE + EAI_BASE,
252 "Service name not supported for socket type"},
253 # endif /*EAI_SERVICE*/
254 # ifdef EAI_SOCKTYPE
255 {EAI_SOCKTYPE + EAI_BASE,
256 "Socket type not supported"},
257 # endif /*EAI_SOCKTYPE*/
258 /* GNU extensions */
259 # ifdef EAI_ALLDONE
260 {EAI_ALLDONE + EAI_BASE,
261 "All requests done"},
262 # endif /*EAI_ALLDONE*/
263 # ifdef EAI_CANCELED
264 {EAI_CANCELED + EAI_BASE,
265 "Request canceled"},
266 # endif /*EAI_BADFLAGS*/
267 # ifdef EAI_INPROGRESS
268 {EAI_INPROGRESS + EAI_BASE,
269 "Processing request in progress"},
270 # endif /*EAI_INPROGRESS*/
271 # ifdef EAI_INTR
272 {EAI_INTR + EAI_BASE,
273 "Interrupted by a signal"},
274 # endif /*EAI_INTR*/
275 # ifdef EAI_NOTCANCELED
276 {EAI_NOTCANCELED + EAI_BASE,
277 "Request not canceled"},
278 # endif /*EAI_NOTCANCELED*/
279 # ifdef EAI_IDN_ENCODE
280 {EAI_IDN_ENCODE + EAI_BASE,
281 "IDN encoding failed"},
282 # endif /*EAI_IDN_ENCODE*/
283 # ifdef NCBI_OS_MSWIN
284 # define DNS_BASE 0
285 # else
286 # define DNS_BASE 200000
287 # endif /*NCBI_OS_MSWIN*/
288 # ifdef HOST_NOT_FOUND
289 {HOST_NOT_FOUND + DNS_BASE,
290 "Host not found"},
291 # endif /*HOST_NOT_FOUND*/
292 # ifdef TRY_AGAIN
293 {TRY_AGAIN + DNS_BASE,
294 "DNS server failure"},
295 # endif /*TRY_AGAIN*/
296 # ifdef NO_RECOVERY
297 {NO_RECOVERY + DNS_BASE,
298 "Unrecoverable DNS error"},
299 # endif /*NO_RECOVERY*/
300 # ifdef NO_ADDRESS
301 {NO_ADDRESS + DNS_BASE,
302 "No address record found in DNS"},
303 # endif /*NO_ADDRESS*/
304 # ifdef NO_DATA
305 {NO_DATA + DNS_BASE,
306 "No DNS data of requested type"},
307 # endif /*NO_DATA*/
308
309 /* Last dummy entry - must be present */
310 {0, 0}
311 };
312 #if defined(NCBI_OS_LINUX) || defined(NCBI_OS_CYGWIN)
313 /* To work correctly, descending order of offsets is required here */
314 static const struct {
315 int erroff;
316 const char* (*errfun)(int errnum);
317 } errsup[] = {
318 # ifdef __GLIBC__
319 { DNS_BASE, hstrerror },
320 # endif /*__GLIBC__*/
321 # if defined(HAVE_GETADDRINFO) || defined(HAVE_GETNAMEINFO)
322 { EAI_BASE, gai_strerror },
323 # endif /*HAVE_GETADDRINFO || HAVE_GETNAMEINFO*/
324 /* Last dummy entry - must present */
325 { 0, 0 }
326 };
327 #endif /*NCBI_OS_LINUX || NCBI_OS_CYGWIN*/
328 size_t i;
329
330 if (!error)
331 return 0;
332
333 #if defined(NCBI_OS_LINUX) || defined(NCBI_OS_CYGWIN)
334 for (i = 0; i < sizeof(errsup) / sizeof(errsup[0]) - 1/*dummy*/; ++i) {
335 if (errsup[i].erroff - 10000 < error
336 && error < errsup[i].erroff + 10000) {
337 const char* errstr = errsup[i].errfun(error - errsup[i].erroff);
338 if (errstr && *errstr && strncasecmp(errstr, "Unknown ", 8)!=0)
339 return ERR_STRDUP(errstr);
340 }
341 }
342 #endif /*NCBI_OS_LINUX || NCBI_OS_CYGWIN*/
343
344 for (i = 0; i < sizeof(errmap) / sizeof(errmap[0]) - 1/*dummy*/; ++i) {
345 if (errmap[i].errnum == error)
346 return ERR_STRDUP(errmap[i].errstr);
347 }
348
349 # if defined(NCBI_OS_MSWIN) && defined(_UNICODE)
350 return UTIL_TcharToUtf8(_wcserror(error));
351 # else
352 return ERR_STRDUP(strerror(error));
353 # endif /*NCBI_OS_MSWIN && _UNICODE*/
354 }
355
356
357 #endif /*NCBI_INCLUDE_STRERROR_C*/
358