Annotation of embedaddon/curl/lib/strerror.c, revision 1.1.1.1
1.1 misho 1: /***************************************************************************
2: * _ _ ____ _
3: * Project ___| | | | _ \| |
4: * / __| | | | |_) | |
5: * | (__| |_| | _ <| |___
6: * \___|\___/|_| \_\_____|
7: *
8: * Copyright (C) 2004 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
9: *
10: * This software is licensed as described in the file COPYING, which
11: * you should have received as part of this distribution. The terms
12: * are also available at https://curl.haxx.se/docs/copyright.html.
13: *
14: * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15: * copies of the Software, and permit persons to whom the Software is
16: * furnished to do so, under the terms of the COPYING file.
17: *
18: * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19: * KIND, either express or implied.
20: *
21: ***************************************************************************/
22:
23: #include "curl_setup.h"
24:
25: #ifdef HAVE_STRERROR_R
26: # if (!defined(HAVE_POSIX_STRERROR_R) && \
27: !defined(HAVE_GLIBC_STRERROR_R) && \
28: !defined(HAVE_VXWORKS_STRERROR_R)) || \
29: (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \
30: (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \
31: (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R))
32: # error "strerror_r MUST be either POSIX, glibc or vxworks-style"
33: # endif
34: #endif
35:
36: #include <curl/curl.h>
37:
38: #ifdef USE_LIBIDN2
39: #include <idn2.h>
40: #endif
41:
42: #ifdef USE_WINDOWS_SSPI
43: #include "curl_sspi.h"
44: #endif
45:
46: #include "strerror.h"
47: /* The last 3 #include files should be in this order */
48: #include "curl_printf.h"
49: #include "curl_memory.h"
50: #include "memdebug.h"
51:
52: #if defined(WIN32) || defined(_WIN32_WCE)
53: #define PRESERVE_WINDOWS_ERROR_CODE
54: #endif
55:
56: const char *
57: curl_easy_strerror(CURLcode error)
58: {
59: #ifndef CURL_DISABLE_VERBOSE_STRINGS
60: switch(error) {
61: case CURLE_OK:
62: return "No error";
63:
64: case CURLE_UNSUPPORTED_PROTOCOL:
65: return "Unsupported protocol";
66:
67: case CURLE_FAILED_INIT:
68: return "Failed initialization";
69:
70: case CURLE_URL_MALFORMAT:
71: return "URL using bad/illegal format or missing URL";
72:
73: case CURLE_NOT_BUILT_IN:
74: return "A requested feature, protocol or option was not found built-in in"
75: " this libcurl due to a build-time decision.";
76:
77: case CURLE_COULDNT_RESOLVE_PROXY:
78: return "Couldn't resolve proxy name";
79:
80: case CURLE_COULDNT_RESOLVE_HOST:
81: return "Couldn't resolve host name";
82:
83: case CURLE_COULDNT_CONNECT:
84: return "Couldn't connect to server";
85:
86: case CURLE_WEIRD_SERVER_REPLY:
87: return "Weird server reply";
88:
89: case CURLE_REMOTE_ACCESS_DENIED:
90: return "Access denied to remote resource";
91:
92: case CURLE_FTP_ACCEPT_FAILED:
93: return "FTP: The server failed to connect to data port";
94:
95: case CURLE_FTP_ACCEPT_TIMEOUT:
96: return "FTP: Accepting server connect has timed out";
97:
98: case CURLE_FTP_PRET_FAILED:
99: return "FTP: The server did not accept the PRET command.";
100:
101: case CURLE_FTP_WEIRD_PASS_REPLY:
102: return "FTP: unknown PASS reply";
103:
104: case CURLE_FTP_WEIRD_PASV_REPLY:
105: return "FTP: unknown PASV reply";
106:
107: case CURLE_FTP_WEIRD_227_FORMAT:
108: return "FTP: unknown 227 response format";
109:
110: case CURLE_FTP_CANT_GET_HOST:
111: return "FTP: can't figure out the host in the PASV response";
112:
113: case CURLE_HTTP2:
114: return "Error in the HTTP2 framing layer";
115:
116: case CURLE_FTP_COULDNT_SET_TYPE:
117: return "FTP: couldn't set file type";
118:
119: case CURLE_PARTIAL_FILE:
120: return "Transferred a partial file";
121:
122: case CURLE_FTP_COULDNT_RETR_FILE:
123: return "FTP: couldn't retrieve (RETR failed) the specified file";
124:
125: case CURLE_QUOTE_ERROR:
126: return "Quote command returned error";
127:
128: case CURLE_HTTP_RETURNED_ERROR:
129: return "HTTP response code said error";
130:
131: case CURLE_WRITE_ERROR:
132: return "Failed writing received data to disk/application";
133:
134: case CURLE_UPLOAD_FAILED:
135: return "Upload failed (at start/before it took off)";
136:
137: case CURLE_READ_ERROR:
138: return "Failed to open/read local data from file/application";
139:
140: case CURLE_OUT_OF_MEMORY:
141: return "Out of memory";
142:
143: case CURLE_OPERATION_TIMEDOUT:
144: return "Timeout was reached";
145:
146: case CURLE_FTP_PORT_FAILED:
147: return "FTP: command PORT failed";
148:
149: case CURLE_FTP_COULDNT_USE_REST:
150: return "FTP: command REST failed";
151:
152: case CURLE_RANGE_ERROR:
153: return "Requested range was not delivered by the server";
154:
155: case CURLE_HTTP_POST_ERROR:
156: return "Internal problem setting up the POST";
157:
158: case CURLE_SSL_CONNECT_ERROR:
159: return "SSL connect error";
160:
161: case CURLE_BAD_DOWNLOAD_RESUME:
162: return "Couldn't resume download";
163:
164: case CURLE_FILE_COULDNT_READ_FILE:
165: return "Couldn't read a file:// file";
166:
167: case CURLE_LDAP_CANNOT_BIND:
168: return "LDAP: cannot bind";
169:
170: case CURLE_LDAP_SEARCH_FAILED:
171: return "LDAP: search failed";
172:
173: case CURLE_FUNCTION_NOT_FOUND:
174: return "A required function in the library was not found";
175:
176: case CURLE_ABORTED_BY_CALLBACK:
177: return "Operation was aborted by an application callback";
178:
179: case CURLE_BAD_FUNCTION_ARGUMENT:
180: return "A libcurl function was given a bad argument";
181:
182: case CURLE_INTERFACE_FAILED:
183: return "Failed binding local connection end";
184:
185: case CURLE_TOO_MANY_REDIRECTS :
186: return "Number of redirects hit maximum amount";
187:
188: case CURLE_UNKNOWN_OPTION:
189: return "An unknown option was passed in to libcurl";
190:
191: case CURLE_TELNET_OPTION_SYNTAX :
192: return "Malformed telnet option";
193:
194: case CURLE_GOT_NOTHING:
195: return "Server returned nothing (no headers, no data)";
196:
197: case CURLE_SSL_ENGINE_NOTFOUND:
198: return "SSL crypto engine not found";
199:
200: case CURLE_SSL_ENGINE_SETFAILED:
201: return "Can not set SSL crypto engine as default";
202:
203: case CURLE_SSL_ENGINE_INITFAILED:
204: return "Failed to initialise SSL crypto engine";
205:
206: case CURLE_SEND_ERROR:
207: return "Failed sending data to the peer";
208:
209: case CURLE_RECV_ERROR:
210: return "Failure when receiving data from the peer";
211:
212: case CURLE_SSL_CERTPROBLEM:
213: return "Problem with the local SSL certificate";
214:
215: case CURLE_SSL_CIPHER:
216: return "Couldn't use specified SSL cipher";
217:
218: case CURLE_PEER_FAILED_VERIFICATION:
219: return "SSL peer certificate or SSH remote key was not OK";
220:
221: case CURLE_SSL_CACERT_BADFILE:
222: return "Problem with the SSL CA cert (path? access rights?)";
223:
224: case CURLE_BAD_CONTENT_ENCODING:
225: return "Unrecognized or bad HTTP Content or Transfer-Encoding";
226:
227: case CURLE_LDAP_INVALID_URL:
228: return "Invalid LDAP URL";
229:
230: case CURLE_FILESIZE_EXCEEDED:
231: return "Maximum file size exceeded";
232:
233: case CURLE_USE_SSL_FAILED:
234: return "Requested SSL level failed";
235:
236: case CURLE_SSL_SHUTDOWN_FAILED:
237: return "Failed to shut down the SSL connection";
238:
239: case CURLE_SSL_CRL_BADFILE:
240: return "Failed to load CRL file (path? access rights?, format?)";
241:
242: case CURLE_SSL_ISSUER_ERROR:
243: return "Issuer check against peer certificate failed";
244:
245: case CURLE_SEND_FAIL_REWIND:
246: return "Send failed since rewinding of the data stream failed";
247:
248: case CURLE_LOGIN_DENIED:
249: return "Login denied";
250:
251: case CURLE_TFTP_NOTFOUND:
252: return "TFTP: File Not Found";
253:
254: case CURLE_TFTP_PERM:
255: return "TFTP: Access Violation";
256:
257: case CURLE_REMOTE_DISK_FULL:
258: return "Disk full or allocation exceeded";
259:
260: case CURLE_TFTP_ILLEGAL:
261: return "TFTP: Illegal operation";
262:
263: case CURLE_TFTP_UNKNOWNID:
264: return "TFTP: Unknown transfer ID";
265:
266: case CURLE_REMOTE_FILE_EXISTS:
267: return "Remote file already exists";
268:
269: case CURLE_TFTP_NOSUCHUSER:
270: return "TFTP: No such user";
271:
272: case CURLE_CONV_FAILED:
273: return "Conversion failed";
274:
275: case CURLE_CONV_REQD:
276: return "Caller must register CURLOPT_CONV_ callback options";
277:
278: case CURLE_REMOTE_FILE_NOT_FOUND:
279: return "Remote file not found";
280:
281: case CURLE_SSH:
282: return "Error in the SSH layer";
283:
284: case CURLE_AGAIN:
285: return "Socket not ready for send/recv";
286:
287: case CURLE_RTSP_CSEQ_ERROR:
288: return "RTSP CSeq mismatch or invalid CSeq";
289:
290: case CURLE_RTSP_SESSION_ERROR:
291: return "RTSP session error";
292:
293: case CURLE_FTP_BAD_FILE_LIST:
294: return "Unable to parse FTP file list";
295:
296: case CURLE_CHUNK_FAILED:
297: return "Chunk callback failed";
298:
299: case CURLE_NO_CONNECTION_AVAILABLE:
300: return "The max connection limit is reached";
301:
302: case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
303: return "SSL public key does not match pinned public key";
304:
305: case CURLE_SSL_INVALIDCERTSTATUS:
306: return "SSL server certificate status verification FAILED";
307:
308: case CURLE_HTTP2_STREAM:
309: return "Stream error in the HTTP/2 framing layer";
310:
311: case CURLE_RECURSIVE_API_CALL:
312: return "API function called from within callback";
313:
314: case CURLE_AUTH_ERROR:
315: return "An authentication function returned an error";
316:
317: case CURLE_HTTP3:
318: return "HTTP/3 error";
319:
320: case CURLE_QUIC_CONNECT_ERROR:
321: return "QUIC connection error";
322:
323: /* error codes not used by current libcurl */
324: case CURLE_OBSOLETE20:
325: case CURLE_OBSOLETE24:
326: case CURLE_OBSOLETE29:
327: case CURLE_OBSOLETE32:
328: case CURLE_OBSOLETE40:
329: case CURLE_OBSOLETE44:
330: case CURLE_OBSOLETE46:
331: case CURLE_OBSOLETE50:
332: case CURLE_OBSOLETE51:
333: case CURLE_OBSOLETE57:
334: case CURL_LAST:
335: break;
336: }
337: /*
338: * By using a switch, gcc -Wall will complain about enum values
339: * which do not appear, helping keep this function up-to-date.
340: * By using gcc -Wall -Werror, you can't forget.
341: *
342: * A table would not have the same benefit. Most compilers will
343: * generate code very similar to a table in any case, so there
344: * is little performance gain from a table. And something is broken
345: * for the user's application, anyways, so does it matter how fast
346: * it _doesn't_ work?
347: *
348: * The line number for the error will be near this comment, which
349: * is why it is here, and not at the start of the switch.
350: */
351: return "Unknown error";
352: #else
353: if(!error)
354: return "No error";
355: else
356: return "Error";
357: #endif
358: }
359:
360: const char *
361: curl_multi_strerror(CURLMcode error)
362: {
363: #ifndef CURL_DISABLE_VERBOSE_STRINGS
364: switch(error) {
365: case CURLM_CALL_MULTI_PERFORM:
366: return "Please call curl_multi_perform() soon";
367:
368: case CURLM_OK:
369: return "No error";
370:
371: case CURLM_BAD_HANDLE:
372: return "Invalid multi handle";
373:
374: case CURLM_BAD_EASY_HANDLE:
375: return "Invalid easy handle";
376:
377: case CURLM_OUT_OF_MEMORY:
378: return "Out of memory";
379:
380: case CURLM_INTERNAL_ERROR:
381: return "Internal error";
382:
383: case CURLM_BAD_SOCKET:
384: return "Invalid socket argument";
385:
386: case CURLM_UNKNOWN_OPTION:
387: return "Unknown option";
388:
389: case CURLM_ADDED_ALREADY:
390: return "The easy handle is already added to a multi handle";
391:
392: case CURLM_RECURSIVE_API_CALL:
393: return "API function called from within callback";
394:
395: case CURLM_WAKEUP_FAILURE:
396: return "Wakeup is unavailable or failed";
397:
398: case CURLM_BAD_FUNCTION_ARGUMENT:
399: return "A libcurl function was given a bad argument";
400:
401: case CURLM_LAST:
402: break;
403: }
404:
405: return "Unknown error";
406: #else
407: if(error == CURLM_OK)
408: return "No error";
409: else
410: return "Error";
411: #endif
412: }
413:
414: const char *
415: curl_share_strerror(CURLSHcode error)
416: {
417: #ifndef CURL_DISABLE_VERBOSE_STRINGS
418: switch(error) {
419: case CURLSHE_OK:
420: return "No error";
421:
422: case CURLSHE_BAD_OPTION:
423: return "Unknown share option";
424:
425: case CURLSHE_IN_USE:
426: return "Share currently in use";
427:
428: case CURLSHE_INVALID:
429: return "Invalid share handle";
430:
431: case CURLSHE_NOMEM:
432: return "Out of memory";
433:
434: case CURLSHE_NOT_BUILT_IN:
435: return "Feature not enabled in this library";
436:
437: case CURLSHE_LAST:
438: break;
439: }
440:
441: return "CURLSHcode unknown";
442: #else
443: if(error == CURLSHE_OK)
444: return "No error";
445: else
446: return "Error";
447: #endif
448: }
449:
450: #ifdef USE_WINSOCK
451: /* This is a helper function for Curl_strerror that converts Winsock error
452: * codes (WSAGetLastError) to error messages.
453: * Returns NULL if no error message was found for error code.
454: */
455: static const char *
456: get_winsock_error (int err, char *buf, size_t len)
457: {
458: #ifndef CURL_DISABLE_VERBOSE_STRINGS
459: const char *p;
460: #endif
461:
462: if(!len)
463: return NULL;
464:
465: *buf = '\0';
466:
467: #ifdef CURL_DISABLE_VERBOSE_STRINGS
468: (void)err;
469: return NULL;
470: #else
471: switch(err) {
472: case WSAEINTR:
473: p = "Call interrupted";
474: break;
475: case WSAEBADF:
476: p = "Bad file";
477: break;
478: case WSAEACCES:
479: p = "Bad access";
480: break;
481: case WSAEFAULT:
482: p = "Bad argument";
483: break;
484: case WSAEINVAL:
485: p = "Invalid arguments";
486: break;
487: case WSAEMFILE:
488: p = "Out of file descriptors";
489: break;
490: case WSAEWOULDBLOCK:
491: p = "Call would block";
492: break;
493: case WSAEINPROGRESS:
494: case WSAEALREADY:
495: p = "Blocking call in progress";
496: break;
497: case WSAENOTSOCK:
498: p = "Descriptor is not a socket";
499: break;
500: case WSAEDESTADDRREQ:
501: p = "Need destination address";
502: break;
503: case WSAEMSGSIZE:
504: p = "Bad message size";
505: break;
506: case WSAEPROTOTYPE:
507: p = "Bad protocol";
508: break;
509: case WSAENOPROTOOPT:
510: p = "Protocol option is unsupported";
511: break;
512: case WSAEPROTONOSUPPORT:
513: p = "Protocol is unsupported";
514: break;
515: case WSAESOCKTNOSUPPORT:
516: p = "Socket is unsupported";
517: break;
518: case WSAEOPNOTSUPP:
519: p = "Operation not supported";
520: break;
521: case WSAEAFNOSUPPORT:
522: p = "Address family not supported";
523: break;
524: case WSAEPFNOSUPPORT:
525: p = "Protocol family not supported";
526: break;
527: case WSAEADDRINUSE:
528: p = "Address already in use";
529: break;
530: case WSAEADDRNOTAVAIL:
531: p = "Address not available";
532: break;
533: case WSAENETDOWN:
534: p = "Network down";
535: break;
536: case WSAENETUNREACH:
537: p = "Network unreachable";
538: break;
539: case WSAENETRESET:
540: p = "Network has been reset";
541: break;
542: case WSAECONNABORTED:
543: p = "Connection was aborted";
544: break;
545: case WSAECONNRESET:
546: p = "Connection was reset";
547: break;
548: case WSAENOBUFS:
549: p = "No buffer space";
550: break;
551: case WSAEISCONN:
552: p = "Socket is already connected";
553: break;
554: case WSAENOTCONN:
555: p = "Socket is not connected";
556: break;
557: case WSAESHUTDOWN:
558: p = "Socket has been shut down";
559: break;
560: case WSAETOOMANYREFS:
561: p = "Too many references";
562: break;
563: case WSAETIMEDOUT:
564: p = "Timed out";
565: break;
566: case WSAECONNREFUSED:
567: p = "Connection refused";
568: break;
569: case WSAELOOP:
570: p = "Loop??";
571: break;
572: case WSAENAMETOOLONG:
573: p = "Name too long";
574: break;
575: case WSAEHOSTDOWN:
576: p = "Host down";
577: break;
578: case WSAEHOSTUNREACH:
579: p = "Host unreachable";
580: break;
581: case WSAENOTEMPTY:
582: p = "Not empty";
583: break;
584: case WSAEPROCLIM:
585: p = "Process limit reached";
586: break;
587: case WSAEUSERS:
588: p = "Too many users";
589: break;
590: case WSAEDQUOT:
591: p = "Bad quota";
592: break;
593: case WSAESTALE:
594: p = "Something is stale";
595: break;
596: case WSAEREMOTE:
597: p = "Remote error";
598: break;
599: #ifdef WSAEDISCON /* missing in SalfordC! */
600: case WSAEDISCON:
601: p = "Disconnected";
602: break;
603: #endif
604: /* Extended Winsock errors */
605: case WSASYSNOTREADY:
606: p = "Winsock library is not ready";
607: break;
608: case WSANOTINITIALISED:
609: p = "Winsock library not initialised";
610: break;
611: case WSAVERNOTSUPPORTED:
612: p = "Winsock version not supported";
613: break;
614:
615: /* getXbyY() errors (already handled in herrmsg):
616: * Authoritative Answer: Host not found */
617: case WSAHOST_NOT_FOUND:
618: p = "Host not found";
619: break;
620:
621: /* Non-Authoritative: Host not found, or SERVERFAIL */
622: case WSATRY_AGAIN:
623: p = "Host not found, try again";
624: break;
625:
626: /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
627: case WSANO_RECOVERY:
628: p = "Unrecoverable error in call to nameserver";
629: break;
630:
631: /* Valid name, no data record of requested type */
632: case WSANO_DATA:
633: p = "No data record of requested type";
634: break;
635:
636: default:
637: return NULL;
638: }
639: strncpy(buf, p, len);
640: buf [len-1] = '\0';
641: return buf;
642: #endif
643: }
644: #endif /* USE_WINSOCK */
645:
646: #if defined(WIN32) || defined(_WIN32_WCE)
647: /* This is a helper function for Curl_strerror that converts Windows API error
648: * codes (GetLastError) to error messages.
649: * Returns NULL if no error message was found for error code.
650: */
651: static const char *
652: get_winapi_error(int err, char *buf, size_t buflen)
653: {
654: char *p;
655:
656: if(!buflen)
657: return NULL;
658:
659: *buf = '\0';
660:
661: #ifdef _WIN32_WCE
662: {
663: wchar_t wbuf[256];
664: wbuf[0] = L'\0';
665:
666: if(FormatMessage((FORMAT_MESSAGE_FROM_SYSTEM |
667: FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
668: LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
669: size_t written = wcstombs(buf, wbuf, buflen - 1);
670: if(written != (size_t)-1)
671: buf[written] = '\0';
672: else
673: *buf = '\0';
674: }
675: }
676: #else
677: if(!FormatMessageA((FORMAT_MESSAGE_FROM_SYSTEM |
678: FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
679: LANG_NEUTRAL, buf, (DWORD)buflen, NULL)) {
680: *buf = '\0';
681: }
682: #endif
683:
684: /* Truncate multiple lines */
685: p = strchr(buf, '\n');
686: if(p) {
687: if(p > buf && *(p-1) == '\r')
688: *(p-1) = '\0';
689: else
690: *p = '\0';
691: }
692:
693: return (*buf ? buf : NULL);
694: }
695: #endif /* WIN32 || _WIN32_WCE */
696:
697: /*
698: * Our thread-safe and smart strerror() replacement.
699: *
700: * The 'err' argument passed in to this function MUST be a true errno number
701: * as reported on this system. We do no range checking on the number before
702: * we pass it to the "number-to-message" conversion function and there might
703: * be systems that don't do proper range checking in there themselves.
704: *
705: * We don't do range checking (on systems other than Windows) since there is
706: * no good reliable and portable way to do it.
707: *
708: * On Windows different types of error codes overlap. This function has an
709: * order of preference when trying to match error codes:
710: * CRT (errno), Winsock (WSAGetLastError), Windows API (GetLastError).
711: *
712: * It may be more correct to call one of the variant functions instead:
713: * Call Curl_sspi_strerror if the error code is definitely Windows SSPI.
714: * Call Curl_winapi_strerror if the error code is definitely Windows API.
715: */
716: const char *Curl_strerror(int err, char *buf, size_t buflen)
717: {
718: #ifdef PRESERVE_WINDOWS_ERROR_CODE
719: DWORD old_win_err = GetLastError();
720: #endif
721: int old_errno = errno;
722: char *p;
723: size_t max;
724:
725: if(!buflen)
726: return NULL;
727:
728: DEBUGASSERT(err >= 0);
729:
730: max = buflen - 1;
731: *buf = '\0';
732:
733: #if defined(WIN32) || defined(_WIN32_WCE)
734: #if defined(WIN32)
735: /* 'sys_nerr' is the maximum errno number, it is not widely portable */
736: if(err >= 0 && err < sys_nerr)
737: strncpy(buf, strerror(err), max);
738: else
739: #endif
740: {
741: if(
742: #ifdef USE_WINSOCK
743: !get_winsock_error(err, buf, max) &&
744: #endif
745: !get_winapi_error((DWORD)err, buf, max))
746: msnprintf(buf, max, "Unknown error %d (%#x)", err, err);
747: }
748: #else /* not Windows coming up */
749:
750: #if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
751: /*
752: * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
753: * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
754: * message string, or EINVAL if 'errnum' is not a valid error number.
755: */
756: if(0 != strerror_r(err, buf, max)) {
757: if('\0' == buf[0])
758: msnprintf(buf, max, "Unknown error %d", err);
759: }
760: #elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
761: /*
762: * The glibc-style strerror_r() only *might* use the buffer we pass to
763: * the function, but it always returns the error message as a pointer,
764: * so we must copy that string unconditionally (if non-NULL).
765: */
766: {
767: char buffer[256];
768: char *msg = strerror_r(err, buffer, sizeof(buffer));
769: if(msg)
770: strncpy(buf, msg, max);
771: else
772: msnprintf(buf, max, "Unknown error %d", err);
773: }
774: #elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)
775: /*
776: * The vxworks-style strerror_r() does use the buffer we pass to the function.
777: * The buffer size should be at least NAME_MAX (256)
778: */
779: {
780: char buffer[256];
781: if(OK == strerror_r(err, buffer))
782: strncpy(buf, buffer, max);
783: else
784: msnprintf(buf, max, "Unknown error %d", err);
785: }
786: #else
787: {
788: char *msg = strerror(err);
789: if(msg)
790: strncpy(buf, msg, max);
791: else
792: msnprintf(buf, max, "Unknown error %d", err);
793: }
794: #endif
795:
796: #endif /* end of not Windows */
797:
798: buf[max] = '\0'; /* make sure the string is zero terminated */
799:
800: /* strip trailing '\r\n' or '\n'. */
801: p = strrchr(buf, '\n');
802: if(p && (p - buf) >= 2)
803: *p = '\0';
804: p = strrchr(buf, '\r');
805: if(p && (p - buf) >= 1)
806: *p = '\0';
807:
808: if(errno != old_errno)
809: errno = old_errno;
810:
811: #ifdef PRESERVE_WINDOWS_ERROR_CODE
812: if(old_win_err != GetLastError())
813: SetLastError(old_win_err);
814: #endif
815:
816: return buf;
817: }
818:
819: /*
820: * Curl_winapi_strerror:
821: * Variant of Curl_strerror if the error code is definitely Windows API.
822: */
823: #if defined(WIN32) || defined(_WIN32_WCE)
824: const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
825: {
826: #ifdef PRESERVE_WINDOWS_ERROR_CODE
827: DWORD old_win_err = GetLastError();
828: #endif
829: int old_errno = errno;
830:
831: if(!buflen)
832: return NULL;
833:
834: *buf = '\0';
835:
836: #ifndef CURL_DISABLE_VERBOSE_STRINGS
837: if(!get_winapi_error(err, buf, buflen)) {
838: msnprintf(buf, buflen, "Unknown error %u (0x%08X)", err, err);
839: }
840: #else
841: {
842: const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error";
843: strncpy(buf, txt, buflen);
844: buf[buflen - 1] = '\0';
845: }
846: #endif
847:
848: if(errno != old_errno)
849: errno = old_errno;
850:
851: #ifdef PRESERVE_WINDOWS_ERROR_CODE
852: if(old_win_err != GetLastError())
853: SetLastError(old_win_err);
854: #endif
855:
856: return buf;
857: }
858: #endif /* WIN32 || _WIN32_WCE */
859:
860: #ifdef USE_WINDOWS_SSPI
861: /*
862: * Curl_sspi_strerror:
863: * Variant of Curl_strerror if the error code is definitely Windows SSPI.
864: */
865: const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
866: {
867: #ifdef PRESERVE_WINDOWS_ERROR_CODE
868: DWORD old_win_err = GetLastError();
869: #endif
870: int old_errno = errno;
871: const char *txt;
872:
873: if(!buflen)
874: return NULL;
875:
876: *buf = '\0';
877:
878: #ifndef CURL_DISABLE_VERBOSE_STRINGS
879:
880: switch(err) {
881: case SEC_E_OK:
882: txt = "No error";
883: break;
884: #define SEC2TXT(sec) case sec: txt = #sec; break
885: SEC2TXT(CRYPT_E_REVOKED);
886: SEC2TXT(SEC_E_ALGORITHM_MISMATCH);
887: SEC2TXT(SEC_E_BAD_BINDINGS);
888: SEC2TXT(SEC_E_BAD_PKGID);
889: SEC2TXT(SEC_E_BUFFER_TOO_SMALL);
890: SEC2TXT(SEC_E_CANNOT_INSTALL);
891: SEC2TXT(SEC_E_CANNOT_PACK);
892: SEC2TXT(SEC_E_CERT_EXPIRED);
893: SEC2TXT(SEC_E_CERT_UNKNOWN);
894: SEC2TXT(SEC_E_CERT_WRONG_USAGE);
895: SEC2TXT(SEC_E_CONTEXT_EXPIRED);
896: SEC2TXT(SEC_E_CROSSREALM_DELEGATION_FAILURE);
897: SEC2TXT(SEC_E_CRYPTO_SYSTEM_INVALID);
898: SEC2TXT(SEC_E_DECRYPT_FAILURE);
899: SEC2TXT(SEC_E_DELEGATION_POLICY);
900: SEC2TXT(SEC_E_DELEGATION_REQUIRED);
901: SEC2TXT(SEC_E_DOWNGRADE_DETECTED);
902: SEC2TXT(SEC_E_ENCRYPT_FAILURE);
903: SEC2TXT(SEC_E_ILLEGAL_MESSAGE);
904: SEC2TXT(SEC_E_INCOMPLETE_CREDENTIALS);
905: SEC2TXT(SEC_E_INCOMPLETE_MESSAGE);
906: SEC2TXT(SEC_E_INSUFFICIENT_MEMORY);
907: SEC2TXT(SEC_E_INTERNAL_ERROR);
908: SEC2TXT(SEC_E_INVALID_HANDLE);
909: SEC2TXT(SEC_E_INVALID_PARAMETER);
910: SEC2TXT(SEC_E_INVALID_TOKEN);
911: SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED);
912: SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED_KDC);
913: SEC2TXT(SEC_E_KDC_CERT_EXPIRED);
914: SEC2TXT(SEC_E_KDC_CERT_REVOKED);
915: SEC2TXT(SEC_E_KDC_INVALID_REQUEST);
916: SEC2TXT(SEC_E_KDC_UNABLE_TO_REFER);
917: SEC2TXT(SEC_E_KDC_UNKNOWN_ETYPE);
918: SEC2TXT(SEC_E_LOGON_DENIED);
919: SEC2TXT(SEC_E_MAX_REFERRALS_EXCEEDED);
920: SEC2TXT(SEC_E_MESSAGE_ALTERED);
921: SEC2TXT(SEC_E_MULTIPLE_ACCOUNTS);
922: SEC2TXT(SEC_E_MUST_BE_KDC);
923: SEC2TXT(SEC_E_NOT_OWNER);
924: SEC2TXT(SEC_E_NO_AUTHENTICATING_AUTHORITY);
925: SEC2TXT(SEC_E_NO_CREDENTIALS);
926: SEC2TXT(SEC_E_NO_IMPERSONATION);
927: SEC2TXT(SEC_E_NO_IP_ADDRESSES);
928: SEC2TXT(SEC_E_NO_KERB_KEY);
929: SEC2TXT(SEC_E_NO_PA_DATA);
930: SEC2TXT(SEC_E_NO_S4U_PROT_SUPPORT);
931: SEC2TXT(SEC_E_NO_TGT_REPLY);
932: SEC2TXT(SEC_E_OUT_OF_SEQUENCE);
933: SEC2TXT(SEC_E_PKINIT_CLIENT_FAILURE);
934: SEC2TXT(SEC_E_PKINIT_NAME_MISMATCH);
935: SEC2TXT(SEC_E_POLICY_NLTM_ONLY);
936: SEC2TXT(SEC_E_QOP_NOT_SUPPORTED);
937: SEC2TXT(SEC_E_REVOCATION_OFFLINE_C);
938: SEC2TXT(SEC_E_REVOCATION_OFFLINE_KDC);
939: SEC2TXT(SEC_E_SECPKG_NOT_FOUND);
940: SEC2TXT(SEC_E_SECURITY_QOS_FAILED);
941: SEC2TXT(SEC_E_SHUTDOWN_IN_PROGRESS);
942: SEC2TXT(SEC_E_SMARTCARD_CERT_EXPIRED);
943: SEC2TXT(SEC_E_SMARTCARD_CERT_REVOKED);
944: SEC2TXT(SEC_E_SMARTCARD_LOGON_REQUIRED);
945: SEC2TXT(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED);
946: SEC2TXT(SEC_E_TARGET_UNKNOWN);
947: SEC2TXT(SEC_E_TIME_SKEW);
948: SEC2TXT(SEC_E_TOO_MANY_PRINCIPALS);
949: SEC2TXT(SEC_E_UNFINISHED_CONTEXT_DELETED);
950: SEC2TXT(SEC_E_UNKNOWN_CREDENTIALS);
951: SEC2TXT(SEC_E_UNSUPPORTED_FUNCTION);
952: SEC2TXT(SEC_E_UNSUPPORTED_PREAUTH);
953: SEC2TXT(SEC_E_UNTRUSTED_ROOT);
954: SEC2TXT(SEC_E_WRONG_CREDENTIAL_HANDLE);
955: SEC2TXT(SEC_E_WRONG_PRINCIPAL);
956: SEC2TXT(SEC_I_COMPLETE_AND_CONTINUE);
957: SEC2TXT(SEC_I_COMPLETE_NEEDED);
958: SEC2TXT(SEC_I_CONTEXT_EXPIRED);
959: SEC2TXT(SEC_I_CONTINUE_NEEDED);
960: SEC2TXT(SEC_I_INCOMPLETE_CREDENTIALS);
961: SEC2TXT(SEC_I_LOCAL_LOGON);
962: SEC2TXT(SEC_I_NO_LSA_CONTEXT);
963: SEC2TXT(SEC_I_RENEGOTIATE);
964: SEC2TXT(SEC_I_SIGNATURE_NEEDED);
965: default:
966: txt = "Unknown error";
967: }
968:
969: if(err == SEC_E_ILLEGAL_MESSAGE) {
970: msnprintf(buf, buflen,
971: "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs "
972: "when a fatal SSL/TLS alert is received (e.g. handshake failed)."
973: " More detail may be available in the Windows System event log.",
974: err);
975: }
976: else {
977: char txtbuf[80];
978: char msgbuf[256];
979:
980: msnprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err);
981:
982: if(get_winapi_error(err, msgbuf, sizeof(msgbuf)))
983: msnprintf(buf, buflen, "%s - %s", txtbuf, msgbuf);
984: else {
985: strncpy(buf, txtbuf, buflen);
986: buf[buflen - 1] = '\0';
987: }
988: }
989:
990: #else
991: if(err == SEC_E_OK)
992: txt = "No error";
993: else
994: txt = "Error";
995: strncpy(buf, txt, buflen);
996: buf[buflen - 1] = '\0';
997: #endif
998:
999: if(errno != old_errno)
1000: errno = old_errno;
1001:
1002: #ifdef PRESERVE_WINDOWS_ERROR_CODE
1003: if(old_win_err != GetLastError())
1004: SetLastError(old_win_err);
1005: #endif
1006:
1007: return buf;
1008: }
1009: #endif /* USE_WINDOWS_SSPI */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>